SPOJ TTM To the moon(主席树+区间操作)
2013-02-03 14:45
344 查看
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents
by---cxlove
题目:给定一个序列,查询当前区间和,历史某个时期的区间和,以前区间修改,时间回滚操作
http://www.spoj.com/problems/TTM/
只要搞过可持久化线段树,就会觉得这题其实不难吧。。。
按时间,建立主席树,在上一时间段的基础上,进行区间更新,生成新的主席树。
查询历史区间什么的就直接查询那棵主席树,时间回滚都很简单。
但是实现起来就DT了。。。。
写完也很轻松。。。和之前做的主席树差不多
唯独这是区间更新。。。问题就在这了。。。
和线段树上的区间操作累似,对于线段加了lazy操作。
问题就在:如果当前区间更新,加入lazy,按理是不需要更新子节点的,之后直接push_down就行了
这是普通线段树的做法
但是如果当前区间的左右孩子还是原来的,那么在查询的时候,就容易push_down之后更新了历史版本
在这里错了好久,囧。。。。
但是又不能直接更新到所有叶子节点,那就相当于n棵线段树了。。。n*n*lgn左右的内存,吃不消。。
最后只能先指向原来的,但是在父节点上打上标记,表示如果要push_down的话,两个左右孩子都是历史版本,不能直接更新
那在push_down之前先判断是否是虚节点,如果是的话,就新建两个节点,然后再更新。。。
勉强搞过去了。。。相比于xiaodao的标程来说,内存多了好多。。。。(他是动态的)
by---cxlove
题目:给定一个序列,查询当前区间和,历史某个时期的区间和,以前区间修改,时间回滚操作
http://www.spoj.com/problems/TTM/
只要搞过可持久化线段树,就会觉得这题其实不难吧。。。
按时间,建立主席树,在上一时间段的基础上,进行区间更新,生成新的主席树。
查询历史区间什么的就直接查询那棵主席树,时间回滚都很简单。
但是实现起来就DT了。。。。
写完也很轻松。。。和之前做的主席树差不多
唯独这是区间更新。。。问题就在这了。。。
和线段树上的区间操作累似,对于线段加了lazy操作。
问题就在:如果当前区间更新,加入lazy,按理是不需要更新子节点的,之后直接push_down就行了
这是普通线段树的做法
但是如果当前区间的左右孩子还是原来的,那么在查询的时候,就容易push_down之后更新了历史版本
在这里错了好久,囧。。。。
但是又不能直接更新到所有叶子节点,那就相当于n棵线段树了。。。n*n*lgn左右的内存,吃不消。。
最后只能先指向原来的,但是在父节点上打上标记,表示如果要push_down的话,两个左右孩子都是历史版本,不能直接更新
那在push_down之前先判断是否是虚节点,如果是的话,就新建两个节点,然后再更新。。。
勉强搞过去了。。。相比于xiaodao的标程来说,内存多了好多。。。。(他是动态的)
#include<iostream> #include<cstdio> #include<map> #include<cstring> #include<cmath> #include<vector> #include<algorithm> #include<set> #include<stack> #include<string> #include<ctime> #include<queue> #include<cassert> #define inf 1000000005 #define M 10000005 #define N 110005 #define maxn 210005 #define eps 1e-8 #define zero(a) fabs(a)<eps #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define pb(a) push_back(a) #define mp(a,b) make_pair(a,b) #define mem(a,b) memset(a,b,sizeof(a)) #define LL long long #define MOD 1000000007 #define sqr(a) ((a)*(a)) #define Key_value ch[ch[root][1]][0] #define test puts("OK"); #define pi acos(-1.0) #define lowbit(x) ((-(x))&(x)) #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; int n,q,a ; int T ,tot,lson[M],rson[M],lazy[M],mark[M]; LL sum[M]; void push_up(int root){ sum[root]=sum[lson[root]]+sum[rson[root]]; } void push_down(int root,int l,int r){ if(mark[root]){ sum[tot]=sum[lson[root]]; lazy[tot]=lazy[lson[root]]; lson[tot]=lson[lson[root]]; rson[tot]=rson[lson[root]]; lson[root]=tot++; sum[tot]=sum[rson[root]]; lazy[tot]=lazy[rson[root]]; lson[tot]=lson[rson[root]]; rson[tot]=rson[rson[root]]; rson[root]=tot++; mark[lson[root]]=mark[rson[root]]=1; mark[root]=0; } if(lazy[root]){ int m=(l+r)>>1; lazy[lson[root]]+=lazy[root]; lazy[rson[root]]+=lazy[root]; sum[lson[root]]+=(LL)lazy[root]*(m-l+1); sum[rson[root]]+=(LL)lazy[root]*(r-m); lazy[root]=0; } } int bulid(int l,int r){ int root=tot++; lazy[root]=mark[root]=0; if(l==r){ sum[root]=a[l]; return root; } int m=(l+r)>>1; lson[root]=bulid(l,m); rson[root]=bulid(m+1,r); push_up(root); return root; } int update(int root,int L,int R,int l,int r,int val){ int newroot=tot++; if(L==l&&R==r){ lazy[newroot]=lazy[root]+val; sum[newroot]=sum[root]+(LL)val*(r-l+1); if(l!=r){ lson[newroot]=lson[root]; rson[newroot]=rson[root]; mark[newroot]=1; } return newroot; } lazy[newroot]=0; sum[newroot]=0; mark[newroot]=0; push_down(root,L,R); int m=(L+R)>>1; if(r<=m){ lson[newroot]=update(lson[root],L,m,l,r,val); rson[newroot]=rson[root]; } else if(l>m){ lson[newroot]=lson[root]; rson[newroot]=update(rson[root],m+1,R,l,r,val); } else{ lson[newroot]=update(lson[root],L,m,l,m,val); rson[newroot]=update(rson[root],m+1,R,m+1,r,val); } push_up(newroot); return newroot; } LL query(int root,int L,int R,int l,int r){ if(L==l&&R==r) return sum[root]; push_down(root,L,R); int m=(L+R)>>1; if(r<=m) return query(lson[root],L,m,l,r); else if(l>m) return query(rson[root],m+1,R,l,r); else return (LL)query(lson[root],L,m,l,m)+query(rson[root],m+1,R,m+1,r); } void debug(int root,int l,int r){ cout<<l<<" "<<r<<" "<<sum[root]<<endl; push_down(root,l,r); if(l!=r){ int m=(l+r)>>1; debug(lson[root],l,m); debug(rson[root],m+1,r); } } int main(){ //freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout); while(scanf("%d%d",&n,&q)!=EOF){ tot=0; for(int i=1;i<=n;i++) scanf("%d",&a[i]); T[0]=bulid(1,n); int Time=0; while(q--){ char str[5]; scanf("%s",str); int l,r,k; if(str[0]=='Q'){ scanf("%d%d",&l,&r); printf("%lld\n",query(T[Time],1,n,l,r)); } else if(str[0]=='H'){ scanf("%d%d%d",&l,&r,&k); printf("%lld\n",query(T[k],1,n,l,r)); } else if(str[0]=='C'){ scanf("%d%d%d",&l,&r,&k); T[Time+1]=update(T[Time],1,n,l,r,k); Time++; } else{ scanf("%d",&k); Time=k; } } } return 0; }
相关文章推荐
- SPOJ TTM - To the moon (主席树,区间更新,区间查询)
- vjudge: spoj--to the moon(主席树区间修改)
- SPOJ-TTM - To the moon(主席树,经典)
- SPOJ TTM To the moon(主席树)
- hdu 4348 To the moon(主席树区间操作)
- 【HDU - 4348】To the moon(主席树在线区间更新)
- hdu-4348-To the moon-主席树在线区间更新
- HDU 4348 To the moon 【主席树+区间修改】
- hdu 4348 To the moon (主席树区间更新)
- SPOJ TO THE MOON 主席树(有动态修改)
- hdu 4348 To the moon(主席树,区间更新节省内存,经典)
- HDU 4348 / SPOJ TTM - To the moon
- hdu 4348 To the moon 主席树区间更新
- HDU 4348 To the moon [主席树 区间修改]
- HDU 4348 To the moon(主席树区间修改)
- hdu4348 To the moon(区间修改,区间查询的主席树)
- HDU 4348 To the moon 主席树 + 区间更新
- 【HDU4348】To The Moon-主席树(可持久化线段树)区间修改+区间询问
- hdu-4348-To the moon(主席树更新,区间更新,区间和查询,保存历史版本返回)
- HDU 4348 To the moon(主席树区间更新)