poj 4047金华邀请赛 D题 (线段树+lazy优化)
2012-07-08 07:09
393 查看
/*题意: 给出一个N个数的序列以及一个k(0<k<=n<=200000),m个操作p,x,y,其中 p=0:将x位置的数替换为y p=1:将x y位置的数互换 p=2: 查询x-y位置区间连续k个数的和的最大值 分析:因为要求连续区间的最大,我们可以把区间和当做一个节点,这样区间就代表一个点,点就代表一个区间了,这样就可以把原来1~n个数重新分为1~n-k+1了,所以我们只要建一颗总节点范围为1~n-k+1的线段树,p=0时,他能影响到的区间为[min(1,a-k+1),max(n-k+1,b),这个区间的最大值都变成了maxx+=b-v[a];p=1的类似。p=2时,询问的区间为 a~b-k+1; 最关键的就是线段树的优化,lazy操作。当前我的理解就是:更新的时候如果当前满足的要求,标记lazy,不在往下更新,当不符合要求的时候才继续往下update,并且更新子节点的时候回来必须更新父节点。询问的时候,当符合要求的时候就返回当父节点的值,不符合的时候才往下更新知道可以知道结果就停止了。这样就能达到了不需要更新的就不更新的效果,从而优化了。*/ #include <cstdio> #include <cstring> #include <algorithm> #include<iostream> using namespace std; const int Nmax=200080; int n,m,k,sum; int v[Nmax]; int b[Nmax]; struct Node { int L; int R; int maxx; int lazy;//父节点还没有释放的值 }tree[Nmax*10]; int builttree(int fa,int LL,int RR)//返回根的最大值 { int mid=(LL+RR)/2; tree[fa].L=LL; tree[fa].R=RR; tree[fa].lazy=0; if(LL==RR) { tree[fa].maxx=b[mid]; return b[LL]; } int t=builttree(fa*2,LL,mid); int r=builttree(fa*2+1,mid+1,RR); tree[fa].maxx=max(r,t);//父节点的最大值在建完子树之后才能求出 return tree[fa].maxx; } void down(int fa)//向下更新 { if(tree[fa].L==tree[fa].R) return ; tree[fa*2].lazy+=tree[fa].lazy; tree[fa*2].maxx+=tree[fa].lazy; tree[fa*2+1].lazy+=tree[fa].lazy; tree[fa*2+1].maxx+=tree[fa].lazy; tree[fa].lazy=0; } void up(int fa)//向上更新 { if(tree[fa].L==tree[fa].R)return ; tree[fa].maxx=max(tree[fa*2].maxx,tree[fa*2+1].maxx); } void update(int fa,int LL,int RR,int val) { if(tree[fa].L==LL&&tree[fa].R==RR) { tree[fa].maxx+=val; tree[fa].lazy+=val; return ; } if(tree[fa].lazy) down(fa);//父节点在上次中还没被向下释放的值 int mid=(tree[fa].L+tree[fa].R)/2; if(RR<=mid) update(fa*2,LL,RR,val); else if(LL>mid) update(fa*2+1,LL,RR,val); else { update(fa*2,LL,mid,val); update(fa*2+1,mid+1,RR,val); } up(fa);//必须修改他父亲的值 } int query(int fa,int LL,int RR) { if(tree[fa].L==LL&&tree[fa].R==RR) return tree[fa].maxx; if(tree[fa].lazy) down(fa); int mid=(tree[fa].L+tree[fa].R)/2; if(RR<=mid) return query(fa*2,LL,RR); else if(LL>mid) return query(fa*2+1,LL,RR); else { int r= query(fa*2,LL,mid); int t= query(fa*2+1,mid+1,RR); return max(r,t); } } int main() { int cas; scanf("%d",&cas); while(cas--) { //cin>>n>>m>>k; scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) //cin>>v[i]; scanf("%d",&v[i]); sum=n-k+1; memset(b,0,sizeof(b)); for(int i=1;i<=k;i++) b[1]+=v[i]; for(int i=2;i<=n-k+1;i++) b[i]=b[i-1]-v[i-1]+v[i+k-1]; // for(int i=1;i<=n;i++) // cout<<b[i]<<' '; // cout<<endl; int aa=builttree(1,1,n-k+1); // cout<<aa<<endl; // for(int i=1;i<=n;i++) // cout<<tree[i].maxx<<' '; // cout<<endl; int com; int a,b; for(int i=0;i<m;i++) { //cin>>com>>a>>b; scanf("%d%d%d",&com,&a,&b); if(com==0) { update(1,max(1,a-k+1),min(sum,a),b-v[a]);//注意区间,不要越b数组界 v[a]=b; } else if(com==1) { update(1,max(1,a-k+1),min(a,sum),v[b]-v[a]); update(1,max(1,b-k+1),min(sum,b),v[a]-v[b]); swap(v[a],v[b]); } else if(com==2) { int ans=query(1,a,b-k+1); //cout<<ans<<endl; printf("%d\n",ans); } } } return 0; }
相关文章推荐
- Poj 4047 Garden /2012金华邀请赛D题(线段树)
- poj 4047 Garden 2012金华邀请赛 线段树
- poj 4047 Garden(线段树,伤!12年金华邀请赛D题)
- poj 4052 Hrinity 2012 金华邀请赛 AC自动机 DFA
- POJ 4052 Hrinity (金华邀请赛I题) AC自动机
- POJ 4052 金华邀请赛I题
- poj 4047 Garden 2012金华赛区 (成段更新+区间最值)
- POJ 2012金华邀请赛 (持续更新)
- POJ 4052 金华邀请赛I题
- 金华邀请赛 B题 poj 4045
- 金华邀请赛B题poj 4046(spfa求最短路)
- poj 4044 Score Sequence(暴力,12年金华邀请赛A题)
- POJ 4045 Power Station 2012金华邀请赛B题(树形DP)
- POJ 4049 金华赛区邀请赛F题
- Vector的金华邀请赛小结
- POJ 4047 Garden 解题报告
- 金华邀请赛 G - Necklace 限制polya 这两份代码到底什么意思?
- POJ 4047 Garden 线段树 区间更新
- 2012金华邀请赛解题报告
- POJ - 4047 Garden(线段树成段更新,查询最值)