poj4047(线段树+延迟更新)
2013-06-04 13:14
218 查看
//线段树延迟更新
//将连续相邻的k个数据的和看成一个元素,建立线段树;交换、替代两种操作都可以统一成加法操作
//-------加法
//若当前加法操作的区间和当前所在节点的左右区间相同,则只修改延迟标记adi,和当前区间的最大值sum;若不一致,才开始向下执行加法操作,同时修改最大值
//------查询
//若当前查询的区间和当前所在区间相同,则直接返回结果;若不一致,则向下执行加法操作,同时修改最大值
//将连续相邻的k个数据的和看成一个元素,建立线段树;交换、替代两种操作都可以统一成加法操作
//-------加法
//若当前加法操作的区间和当前所在节点的左右区间相同,则只修改延迟标记adi,和当前区间的最大值sum;若不一致,才开始向下执行加法操作,同时修改最大值
//------查询
//若当前查询的区间和当前所在区间相同,则直接返回结果;若不一致,则向下执行加法操作,同时修改最大值
#include <cstdio> #include <cstring> #include <algorithm> #include<iostream> using namespace std; #define MAX 200009 typedef int ll; int min(int a,int b) { return a<b?a:b; } int max(int a,int b) { return a<b?b:a; } ll a[MAX],da[MAX],ans; struct node { ll left,right,add; ll sum; }tree[MAX*5]; //***************************************************** //建立以left,right为左右边界,将数组da中元素存储在首地址从1开始的tree数组中 int build( ll id, ll left, ll right ) { tree[id].add=0; tree[id].left = left; tree[id].right = right; if( left == right ) { tree[id].sum = da[left]; return tree[id].sum; } else { ll mid = ( left + right )>>1; tree[id].sum=max(build( id <<1, left, mid ), build( id<<1|1, mid + 1, right )); return tree[id].sum; } } //***************************************************************** void down(int id) { if(tree[id].left==tree[id].right) return ; tree[id<<1].add+=tree[id].add; tree[id<<1|1].add+=tree[id].add; tree[id<<1].sum+=tree[id].add; tree[id<<1|1].sum+=tree[id].add; tree[id].add=0; } //修改 //**************************************************** //对区间[left,right]内每个元素进行加adi操作 void updata( ll id, ll left, ll right, ll adi) { if(tree[id].left==left&&tree[id].right==right) { tree[id].add+=adi; tree[id].sum+=adi; return ; } else { if(tree[id].add!=0) { down(id); } ll mid=(tree[id].left+tree[id].right)>>1; if(right<=mid) updata(id<<1,left,right,adi); else if(left>mid) updata(id<<1|1,left,right,adi); else { updata(id<<1,left,mid,adi); updata(id<<1|1,mid+1,right,adi); } if(tree[id].left!=tree[id].right) tree[id].sum=max(tree[id<<1].sum ,tree[id<<1|1].sum); } } //***************************************************************** //3.查询 //***************************************************** //查询区间[left,right]的和 int query(ll id, ll left, ll right) { if( tree[id].left==left&&tree[id].right== right) { return tree[id].sum; } else { if(tree[id].add!=0) { down(id); } ll mid = (tree[id].left+tree[id].right)>>1; if(right<= mid ) return query( id <<1, left,right); else if(left>mid ) return query( id <<1|1,left, right); return max( query( id <<1, left,mid) ,query( id<<1|1, mid+1,right )); } } //***************************************************************** int main() { int n,m,k,i,j,t; cin>>t; while(t--) { scanf("%d%d%d",&n,&m,&k); for(i=1;i<=n;i++) { scanf("%d",&a[i]); da[i]=0; } for(i=1;i<=k;i++) da[1]+=a[i]; for(i=2;i<=n-k+1;i++) da[i]=da[i-1]-a[i-1]+a[i+k-1]; build(1,1,n-k+1); for(i=0;i<m;i++) { int op,x,y; scanf("%d%d%d",&op,&x,&y); if(0==op)//x处用y替换 { updata(1,max(1,x-k+1),min(n-k+1,x),y-a[x]); a[x]=y; } else if(1==op)//将x处和y处元素交换 { if(x==y) continue; updata(1,max(1,x-k+1),min(n-k+1,x),a[y]-a[x]); updata(1,max(1,y-k+1),min(n-k+1,y),a[x]-a[y]); int temp=a[x]; a[x]=a[y]; a[y]=temp; } else if(2==op)//输出[x,y]区间中 { ans=query(1,x,y-k+1);//min(y-k+1,n-k+1)); printf("%d\n",ans); } } } return 0; }
相关文章推荐
- HDU 1698 Just a Hook(线段树延迟更新)
- 区间更新 区间和查询 带有延迟标记 线段树 hdu1698; 附:csa 区间加值,维护最大值
- codevs 1082 线段树练习 3 区间更新+延迟标记
- POJ 3468 A Simple Problem with Integers(线段树 + Lazy Tag(延迟更新))
- 【线段树延迟更新】Codeforces Round #104 (Div. 1) E
- 线段树区间更新模板(lazy延迟标记)(1698)
- 线段树专题#4_蒟蒻训练历程记录_HDU1698_ 延迟标记、区间更新
- hdu 5023 线段树延迟更新+状态压缩
- 线段树区间更新区间求和(转延迟标记精讲)
- [线段树]poj3667 Hotel(区间合并、更新、延迟/懒惰标记
- Poj3468(线段树延迟更新)
- hdu1698 Just a Hook 线段树更新延迟标记
- poj 3468线段树延迟更新
- zoj 1610 Count the Colors(线段树延迟更新)
- hdu 5023 线段树延迟更新+状态压缩
- poj2777(延迟更新+线段树)
- 线段树区间更新延迟标记
- poj3468 A Simple Problem with Integers 线段树 更新延迟
- 杭电 HDU ACM 1698 Just a Hook(线段树 区间更新 延迟标记)
- poj3468 A Simple Problem with Integers 线段树延迟标记区间更新区间求和