1. 程式人生 > >HDU 4383 To The Moon 解題報告

HDU 4383 To The Moon 解題報告

HDU 4383 To The Moon

題意翻譯

已知一個長為\(n\)的序列\(a\),你需要進行下面的四種操作。

C l r d 將區間\([l,r]\)中的數加上\(d\),同時時間加\(1\)

Q l r 查詢當前時間區間\([l,r]\)中所有數的和

H l r t 查詢時間為\(t\)時區間\([l,r]\)中所有數的和

B t 將當前時間置為\(t\)

輸入輸出格式

輸入格式

多組資料

每組資料第一行兩個整數\(n,m\)

第二行\(n\)個整數,代表時間為\(0\)時的數列

後面\(m\)行,每行若干個整數,代表一次操作

輸出格式

每一個查詢操作輸出一行作為答案

輸入輸出樣例

輸入樣例#1

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

2 4
0 0
C 1 1 1
C 2 2 -1
Q 1 2
H 1 2 1

輸出樣例#1

4
55
9
15

0
1

說明

對於所有的資料有\(n,m\le 10^5,|a_i| \le 10^9\),\(|d|\le 10^4\),保證所有操作合法。


沒什麼可說的,就是標記永久化一下進行區間修改。

這方面的細節很多,以後需要多加註意。


Code:

#include <cstdio>
#include <cstring>
#define ll long long
const int N=1e5+10;
int ch[N*30][2],tot,root[N],n,m;
ll sum[N*30],tag[N*30],a[N];
#define ls ch[now][0]
#define rs ch[now][1]
void build(int &now,int l,int r)
{
    now=++tot;
    ls=rs=sum[now]=tag[now]=0;
    if(l==r){sum[now]=a[l];return;}
    int mid=l+r>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    sum[now]=sum[ls]+sum[rs];
}
void change(int las,int &now,int L,int R,int l,int r,ll d)
{
    now=++tot;
    ls=ch[las][0],rs=ch[las][1];
    if(L==l&&R==r)
    {
        tag[now]=tag[las]+d;
        sum[now]=sum[las]+d*(R+1-L);
        ls=ch[las][0],rs=ch[las][1];
        return;
    }
    int Mid=L+R>>1;
    if(r<=Mid) change(ch[las][0],ls,L,Mid,l,r,d);
    else if(l>Mid) change(ch[las][1],rs,Mid+1,R,l,r,d);
    else change(ch[las][0],ls,L,Mid,l,Mid,d),change(ch[las][1],rs,Mid+1,R,Mid+1,r,d);
    tag[now]=tag[las];
    sum[now]=sum[ls]+sum[rs]+tag[now]*(R+1-L);
}
ll query(int now,int L,int R,int l,int r)
{
    if(!now||now>tot) return 0;
    if(l==L&&r==R) return sum[now];
    int Mid=L+R>>1;ll delta=tag[now]*(r+1-l);
    if(r<=Mid) return query(ls,L,Mid,l,r)+delta;
    else if(l>Mid) return query(rs,Mid+1,R,l,r)+delta;
    else return query(ls,L,Mid,l,Mid)+query(rs,Mid+1,R,Mid+1,r)+delta;
}
void work()
{
    tot=0;int t=0;
    for(int i=1;i<=n;i++) scanf("%lld",a+i);
    build(root[0],1,n);
    char op[4];ll d;
    for(int l,r,k,i=1;i<=m;i++)
    {
        scanf("%s",op);
        if(op[0]=='C')
        {
            scanf("%d%d%lld",&l,&r,&d);++t;
            change(root[t-1],root[t],1,n,l,r,d);
        }
        else if(op[0]=='Q'||op[0]=='H')
        {
            scanf("%d%d",&l,&r);
            if(op[0]=='Q') k=t;
            else scanf("%d",&k);
            printf("%lld\n",query(root[k],1,n,l,r));
        }
        else
            scanf("%d",&t),tot=root[t+1]-1;
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF) work();
    return 0;
}

2018.12.2