HDU6315 Naive Operations 2018多校二1007

题目:HDU6315
题意:给定b数组,b数组是1~n的一个排列,然后a数组,长度也是n,而且所有元素起始都为0,接下来有两种针对a数组的操作:
1、 add l r: a[l] 到 a[r] 之间每个元素的值 + 1
2、query l r: 求 (i = 从l到r)∑ (int)(a[i]/b[i])

思路:(打比赛的时候挂机到怀疑人生啊)
线段树维护a % b - b的最大值m,和2操作的答案sum,m起始值为-b,当线段树更新到某个位置的m为0的时候,立即dfs向下传递lazy标记,然后再向上更新sum,完了就恢复m为起始值-b
然后是考虑时间复杂度的问题,数据n和q都是1e5,然后每次查询是logn,关键在于修改,由于b数组是1~n的一个排列,因此,最复杂的修改就是每次都修改整个数组,然后q次修改,那么可以计算得到总共需要dfs的次数也就是qlogn(1修改了q次,2修改了q/2, 3修改了q/3,总共也就是q ln(n) ),平均每次也就是log的复杂度,而dfs复杂度也是log,因此总的时间复杂度也就是 n logn logn
只要知道了思路,直接线段树套上去就是了(树状数组笔者没试过了,因为不是很擅长)

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;

int b[N], ans;

struct node
{
    int l, r, m, lazy, sum;
}t[N << 2];

void push_up(int pos)
{
    t[pos].m = max(t[pos << 1].m, t[pos << 1 | 1].m);
    t[pos].sum = t[pos << 1].sum + t[pos << 1 | 1].sum;
}

void push_down(int pos)
{
    if(t[pos].lazy)
    {
        t[pos << 1].lazy += t[pos].lazy;
        t[pos << 1].m += t[pos].lazy;
        t[pos << 1 | 1].lazy += t[pos].lazy;
        t[pos << 1 | 1].m += t[pos].lazy;
        t[pos].lazy = 0;
    }
}

void build(int l, int r, int pos = 1)
{
    t[pos].lazy = 0;
    t[pos].l = l;
    t[pos].r = r;
    t[pos].sum = 0;
    if(l == r)
    {
        t[pos].m = -b[l];
        return ;
    }
    int mid = (l + r) >> 1;
    build(l, mid, pos << 1);
    build(mid + 1, r, pos << 1 | 1);
    push_up(pos);
}

void dfssum(int pos)
{
    if(t[pos].l == t[pos].r)
    {
        t[pos].sum ++;
        t[pos].m = -b[t[pos].l];
        return ;
    }
    push_down(pos);
    if(t[pos << 1].m == 0)
        dfssum(pos << 1);
    if(t[pos << 1 | 1].m == 0)
        dfssum(pos << 1 | 1);
    push_up(pos);
}

void update(int l, int r, int pos = 1)
{
    if(l <= t[pos].l && t[pos].r <= r)
    {
        t[pos].m += 1;
        t[pos].lazy += 1;
        if(t[pos].m == 0)   dfssum(pos);
        return ;
    }
    push_down(pos);
    int mid = (t[pos].l + t[pos].r) >> 1;
    if(l <= mid)
        update(l, r, pos << 1);
    if(r > mid)
        update(l, r, pos << 1 | 1);
    push_up(pos);
}

void query(int l, int r, int pos = 1)
{
    if(l <= t[pos].l && t[pos].r <= r)
    {
        ans += t[pos].sum;
        return ;
    }
    push_down(pos);
    int mid = (t[pos].l + t[pos].r) >> 1;
    if(l <= mid)
        query(l, r, pos << 1);
    if(r > mid)
        query(l, r, pos << 1 | 1);
}

int main()
{
//  freopen("1.txt", "r", stdin);
    int n, m;
    while(~scanf("%d%d", &n, &m))
    {
        for(int i = 1; i <= n; i ++)
            scanf("%d", b + i);
        build(1, n);
        while(m --)
        {
            char s[10];
            int l, r;
            scanf("%s%d%d", s, &l, &r);
            if(s[0] == 'a')
                update(l, r);
            else
            {
                ans = 0;
                query(l, r);
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_38287798/article/details/81210396
今日推荐