HDU 4348 SPOJ TTM To the moon(操作建树)

题意:给出一个序列,四种操作

C l r d: Adding a constant d for every {Ai | l <= i <= r}, and increase the timestamp by 1, this is the only operation that will cause the timestamp increase. 
Q l r: Querying the current sum of {Ai | l <= i <= r}.
H l r t: Querying a history sum of {Ai | l <= i <= r} in time t.
B t: Back to time t. And once you decide return to a past, you can never be access to a forward edition anymore.

对于操作建树,只有当遇到C时时间戳才上升,时间对应的结点建树,dfs整棵树线段树更新区间得到答案

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f
#define maxn 200005

int n,m;
int fir[maxn],nex[maxn],v[maxn],e_max;
long long sum[4*maxn],tag[4*maxn],ans[maxn];

struct Q
{
    char s[3];
    int l,r,c,id;
    friend bool operator < (Q A,Q B)
    {
        return A.idq[maxn];

void init_()
{
    memset(fir,-1,sizeof fir);
    e_max=0;
}

void add_edge(int s,int t)
{
    int e=e_max++;
    v[e]=t;
    nex[e]=fir[s];
    fir[s]=e;
}

void init(int l,int r,int k)
{
    tag[k]=sum[k]=0;
    if(l==r)
    {
        scanf("%lld",&sum[k]);
        return ;
    }
    int mid=l+r>>1;
    init(l,mid,k<<1);
    init(mid+1,r,k<<1|1);
    sum[k]=sum[k<<1]+sum[k<<1|1];
}

void pushdown(int k,int l,int r)
{
    if(!tag[k]) return ;
    int mid=l+r>>1;
    tag[k<<1]+=tag[k];
    sum[k<<1]+=tag[k]*(mid-l+1);
    tag[k<<1|1]+=tag[k];
    sum[k<<1|1]+=tag[k]*(r-mid);
    tag[k]=0;
}

void update(int d,int s,int t,int l,int r,int k)
{
    if(s==l&&r==t)
    {
        sum[k]+=(r-l+1)*(long long)d;
        tag[k]+=d;
        return ;
    }
    pushdown(k,l,r);
    int mid=l+r>>1;
    if(t<=mid) update(d,s,t,l,mid,k<<1);
    else if(s>mid) update(d,s,t,mid+1,r,k<<1|1);
    else
    {
        update(d,s,mid,l,mid,k<<1);
        update(d,mid+1,t,mid+1,r,k<<1|1);
    }
    sum[k]=sum[k<<1]+sum[k<<1|1];
}

long long query(int s,int t,int l,int r,int k)
{
    if(s==l&&r==t)
    {
        return sum[k];
    }
    pushdown(k,l,r);
    int mid=l+r>>1;
    if(t<=mid) return query(s,t,l,mid,k<<1);
    else if(s>mid) return query(s,t,mid+1,r,k<<1|1);
    else return query(s,mid,l,mid,k<<1)+query(mid+1,t,mid+1,r,k<<1|1);
}

void dfs(int k)
{
    for(int i=fir[k]; ~i; i=nex[i])
    {
        int e=v[i];
        if(q[e].s[0]=='Q')
        {
            ans[q[e].id]=query(q[e].l,q[e].r,1,n,1);
        }
        else if(q[e].s[0]=='C')
        {
            update(q[e].c,q[e].l,q[e].r,1,n,1);
            dfs(e);
            update(-q[e].c,q[e].l,q[e].r,1,n,1);
        }
        else if(q[e].s[0]=='H')
        {
            ans[q[e].id]=query(q[e].l,q[e].r,1,n,1);
        }
    }
}

int ti[maxn];
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init_();
        init(1,n,1);
        int now=0;
        ti[now]=0;
        for(int i=1; i<=m; i++)
        {
            scanf("%s",&q[i].s);
            if(q[i].s[0]=='Q')
            {
                scanf("%d%d",&q[i].l,&q[i].r);
                add_edge(ti[now],i);
            }
            else if(q[i].s[0]=='C')
            {
                scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].c);
                add_edge(ti[now],i);
                ti[++now]=i;
            }
            else if(q[i].s[0]=='H')
            {
                scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].c);
                add_edge(ti[q[i].c],i);
            }
            else
            {
                scanf("%d",&q[i].c);
                now=q[i].c;
            }
            q[i].id=i;
        }
        dfs(0);
        for(int i=1; i<=m; i++)
        {
            if(q[i].s[0]=='H'||q[i].s[0]=='Q')
                printf("%lld\n",ans[i]);
        }
    }
    return 0;
}

你可能感兴趣的:(YY,线段树,===数据结构===)