hdu 4348 To the moon(线段树成段更新) 2012 Multi-University Training Contest 5

来源:互联网 发布:淘宝海外市场前景 编辑:程序博客网 时间:2024/05/16 19:10

To the moon

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 38    Accepted Submission(s): 6


Problem Description
Background
To The Moon is a independent game released in November 2011, it is a role-playing adventure game powered by RPG Maker.
The premise of To The Moon is based around a technology that allows us to permanently reconstruct the memory on dying man. In this problem, we'll give you a chance, to implement the logic behind the scene.

You‘ve been given N integers A[1], A[2],..., A[N]. On these integers, you need to implement the following operations:
1. C l r d: Adding a constant d for every {Ai | l <= i <= r}, and increase the time stamp by 1, this is the only operation that will cause the time stamp increase. 
2. Q l r: Querying the current sum of {Ai | l <= i <= r}.
3. H l r t: Querying a history sum of {Ai | l <= i <= r} in time t.
4. B t: Back to time t. And once you decide return to a past, you can never be access to a forward edition anymore.
.. N, M ≤ 106, |A[i]| ≤ 109, 1 ≤ l ≤ r ≤ N, |d| ≤ 104 .. the system start from time 0, and the first modification is in time 1, t ≥ 0, and won't introduce you to a future state.
 

Input
n m
A1 A2 ... An
... (here following the m operations. )
 

Output
... (for each query, simply print the result. )
 

Sample Input
10 51 2 3 4 5 6 7 8 9 10Q 4 4Q 1 10Q 2 4C 3 6 3Q 2 42 40 0C 1 1 1C 2 2 -1Q 1 2H 1 2 1
 

Sample Output
45591501
 

Source
2012 Multi-University Training Contest 5
 

Recommend
zhuyuanchen520
 

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4348

题意:就是给你一个数列,每次可能将 l~r 的数都加上一个值,并且时间加1,也可能询问 l~r 的数的和,也可能询问时间为 t 时,l~r的数的和,还有可能回到时间 t 的那个状态

分析:其实这么多条件都是来吓唬人的,只要一颗成段更新的线段树就能搞定,前两个要求就是普通的线段树,对于询问之前时间的区间和,只要保存每次询问,当时间到达这个询问指定的时间就询问即可,这里可能出现回到之前的时间点影响到询问,只要每次到达需要的时间就重新询问即可,直到输出再删掉这个询问,对于回到之前的时间点,直接做加的反操作就行,也就是涉及加的操作都减回去,直到时间到达要求即可。。。比赛时细节上出了写问题导致没A掉,悲剧

代码:

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int mm=1111111;struct oper{    int id,l,r,d;}g[mm];__int64 sum[mm<<2],dly[mm<<2],ans[mm];int p[mm],q[mm];int n,m,r;void pushdown(int rt,__int64 l1,__int64 l2){    if(dly[rt])    {        dly[rt<<1]+=dly[rt];        sum[rt<<1]+=dly[rt]*l1;        dly[rt<<1|1]+=dly[rt];        sum[rt<<1|1]+=dly[rt]*l2;        dly[rt]=0;    }}void pushup(int rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int l,int r,int rt){    dly[rt]=0;    if(l==r)    {        scanf("%I64d",&sum[rt]);        return;    }    int m=(l+r)>>1;    build(lson);    build(rson);    pushup(rt);}void update(int L,int R,int d,int l,int r,int rt){    if(L<=l&&R>=r)    {        dly[rt]+=d;        sum[rt]+=(__int64)(r-l+1)*(__int64)d;        return;    }    int m=(l+r)>>1;    pushdown(rt,m-l+1,r-m);    if(L<=m)update(L,R,d,lson);    if(R>m)update(L,R,d,rson);    pushup(rt);}__int64 query(int L,int R,int l,int r,int rt){    if(L<=l&&R>=r)return sum[rt];    int m=(l+r)>>1;    __int64 ret=0;    pushdown(rt,m-l+1,r-m);    if(L<=m)ret=query(L,R,lson);    if(R>m)ret+=query(L,R,rson);    pushup(rt);    return ret;}bool cmp(int a,int b){    return g[a].d<g[b].d;}int find(int l,int r,int t){    int m;    while(l<=r)    {        m=(l+r)>>1;        if(g[q[m]].d>=t)r=m-1;        else l=m+1;    }    return r;}int main(){    char op[5];    int i,j,k,t;    while(~scanf("%d%d",&n,&m))    {        build(1,n,1);        r=0;        for(i=1;i<=m;++i)        {            scanf("%s",op);            if(op[0]=='C')            {                g[i].id=1;                scanf("%d%d%d",&g[i].l,&g[i].r,&g[i].d);            }            if(op[0]=='Q')            {                g[i].id=2;                scanf("%d%d",&g[i].l,&g[i].r);            }            if(op[0]=='H')            {                q[r++]=i;                g[i].id=3;                scanf("%d%d%d",&g[i].l,&g[i].r,&g[i].d);            }            if(op[0]=='B')            {                g[i].id=4;                scanf("%d",&g[i].d);            }            p[i]=i-1;        }        sort(q,q+r,cmp);        j=0;        t=0;        for(k=0;k<r;++k)        {            if(g[q[k]].d<t)continue;            if(g[q[k]].d==t)ans[q[k]]=query(g[q[k]].l,g[q[k]].r,1,n,1);            else break;        }        for(i=1;i<=m;++i)        {            if(g[i].id==1)            {                update(g[i].l,g[i].r,g[i].d,1,n,1);                ++t;                for(k=find(j,r-1,t);k<r;++k)                {                    if(g[q[k]].d<t)continue;                    if(g[q[k]].d==t)ans[q[k]]=query(g[q[k]].l,g[q[k]].r,1,n,1);                    else break;                }            }            if(g[i].id==2)            {                printf("%I64d\n",query(g[i].l,g[i].r,1,n,1));            }            if(g[i].id==3)printf("%I64d\n",ans[i]);            if(g[i].id==4)            {                k=p[i];                while(k&&t>g[i].d)                {                    if(g[k].id==1)update(g[k].l,g[k].r,-g[k].d,1,n,1),--t;                    k=p[k];                }                p[i]=k;                for(k=find(j,r-1,t);k<r;++k)                {                    if(g[q[k]].d<t)continue;                    if(g[q[k]].d==t)ans[q[k]]=query(g[q[k]].l,g[q[k]].r,1,n,1);                    else break;                }            }        }    }    return 0;}


原创粉丝点击