HDU4348To the moon主席树,区间修改

题意:

  一个长度为n的数组,4种操作 :

    (1)C l r d:区间[l,r]中的数都加1,同时当前的时间戳加1 。

    (2)Q l r:查询当前时间戳区间[l,r]中所有数的和 。

    (3)H l r t:查询时间戳t区间[l,r]的和 。

    (4)B t:将当前时间戳置为t 。

(第一次修改t为1;

 

思路:被https://www.cnblogs.com/hsd-/p/6506175.html思路坑了一下午,好吧就是自己没懂

然后看到vjudge上的一个思路;感觉这个思路更清晰;

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
#define pb push_back 
typedef long long ll;
const int maxn = 100009;

struct node {
    int l,r;
    ll sum,lazy;
}T[maxn*40];
int root[maxn],cur,tot;
ll a[maxn];


void build(int l,int r,int &pos)
{
    pos = tot++;
    T[pos].sum = T[pos].lazy = 0;
            // T[pos].l = l,T[pos].r = r;
    if(l==r)
    {
        T[pos].sum = a[l];
        return;
    }
    int mid = (l+r)>>1;
    build(l,mid,T[pos].l);
    build(mid+1,r,T[pos].r);
    T[pos].sum = T[T[pos].l].sum + T[T[pos].r].sum;
}
void update(int L,int R, int &x, int y , int l, int r, int d)//这里的x和上面的pos类似
{
    x = tot++;
    T[x] = T[y];
    
    if(l>=L && r<=R)
    {
        T[x].sum += 1ll*(r - l + 1) * d;                    //这里用目标区间的L,R;因为目标区间每个值都要加上
        T[x].lazy += d;
        return;
    }
    int mid = (l+r)>>1;
    if(L <= mid)
        update(L, R, T[x].l, T[y].l, l, mid, d);
    if(R > mid)                                   
        update(L, R, T[x].r, T[y].r, mid+1,r, d);

    T[x].sum = T[T[x].l].sum + T[T[x].r].sum + 1ll*(r-l+1) * T[x].lazy;
}
ll query(int L,int R,int x,int l,int r)
{
            if(L<=l && R>=r)
            {
                return T[x].sum;
            }
            ll ans = 1ll*T[x].lazy*(min(R,r)-max(L,l) + 1);
            int mid = (l+r)>>1;
            if(R  > mid)
                ans += query(L,R,T[x].r, mid+1, r);
            if(L<=mid)
                ans += query(L,R,T[x].l, l,mid);
            return ans;
}
int main()
{
            int n,m;
            int flag = 0;
            while(~scanf("%d%d", &n, &m))
            {   
                if(flag)puts("");
                flag = 1;
                tot = 0,cur = 0;
                for(int i=1; i<=n; i++)
                {
                    scanf("%lld", &a[i]);
                }
                // root[0] = tot++;
                build(1,n,root[0]); 
                while(m--)
                {
                    char op[20];
                    scanf("%s" , op);
                    if(op[0]=='Q')
                    {
                        int l,r;
                        scanf("%d%d",&l,&r);
                        printf("%lld\n",query(l,r,root[cur],1,n));
                    }
                    else if(op[0]=='C')
                    {
                        int l,r;
                        ll d;
                        scanf("%d%d%lld", &l, &r, &d);
                        cur++;
                        update(l,r,root[cur],root[cur-1], 1, n, d);
                    }
                    else if(op[0]=='H')
                    {   
                        int l,r,t;
                        scanf("%d%d%d",&l,&r,&t);
                        printf("%lld\n",query(l,r,root[t],1,n));
                    }
                    else if(op[0]=='B')
                    {
                        scanf("%d",&cur);
                    }
                }
            }
            return 0;
}

 

posted @ 2018-05-03 16:44  ckxkexing  阅读(203)  评论(0编辑  收藏  举报