poj_4047Garden区间更新_求和
来源:互联网 发布:大数据与社会调查 编辑:程序博客网 时间:2024/06/07 01:53
/* 题意:给出一个N个数的序列以及一个k(0<k<=n<=200000),m个操作p,x,y,其中p=0:将x位置的数替换为yp=1:将x y位置的数互换p=2: 查询x-y位置区间连续k个数的和的最大值 解析:求连续区间和最大,可以讲每个区间(我们取左端点)当做一个点,点的附加信息(线段树结子叶点的值)就等于该区间的连续k个数最大值,可以分为1~k,2~k+1...n-k+1~n,一共从1到n-k+1个点构成线段树。线段树中除了子叶结点,其他结点都保存的是子叶结点中的最大值。当x位置值改变时,影响的范围为: 注:我们都是以区间的左端点存入线段树; (1)假设x位置是某区间的右端点,则其左端点为x-k+1,但是最小端点是从1开始,x-k+1可能小于1,因此要取这两者最大值; (2)假设x位置是某区间的左端点,再次说明下,我们是以区间的左端点代表该区间存入线段树,因此当x为左端点时要与最大左端点n-k+1比较,取最小值; 求出x位置影响范围后,更新区间[max(1,x-k+1),min(x,n-k+1)],找到更新结点后,回溯向上更新即Getmax函数,当p==1时,区间最值变为_max=_max-v[x]+y;当p==2时,相当于两次p==1的操作,_max=_max-v[x]+v[y],_max=_max-v[y]+v]x];每次某位置值改变后,要在原数组中同时更改 最后查询x到y位置区间最值时,我们是以区间左端点代表区间,在线段树中只需查询l=x,r=y-k+1即可*/#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;#define INF 0x3f3f3f3f#define inf -0x3f3f3f3f#define mem0(a) memset(a,0,sizeof(a))const int maxn = 200000+10;int sum;int v[maxn],b[maxn];struct node{ int l,r,_max,lazy;}a[maxn<<2];void Getmax(int cur){ a[cur]._max = max(a[cur<<1]._max,a[cur<<1|1]._max);}void build(int l,int r,int cur){ a[cur].l = l; a[cur].r = r; a[cur].lazy = 0; int mid = (l + r )>>1; if(l == r){ a[cur]._max = b[l]; return ; } build(l,mid,cur<<1); build(mid+1,r,cur<<1|1); Getmax(cur);}void pushdown(int cur){ if(a[cur].lazy){ //设置左右孩子节点的标志域,因为孩子节点可能被多次延迟标记又没有向下传递 //所以是 “+=” a[cur<<1].lazy += a[cur].lazy; a[cur<<1|1].lazy += a[cur].lazy; //根据标志域设置孩子节点的值。因为我们是求区间最大值,因此当区间内每个元 //素加上一个值时,区间的最大值也加上这个值 a[cur<<1]._max += a[cur].lazy; a[cur<<1|1]._max += a[cur].lazy; a[cur].lazy = 0;//清除标记 }}void update(int l,int r,int v,int cur){ //当前节点区间包含在更新区间内 if( l <= a[cur].l && r >= a[cur].r){ a[cur]._max += v; a[cur].lazy += v; return ; } pushdown(cur); //延迟标记向下传递 //更新左右孩子节点 int mid = (a[cur].l + a[cur].r )>>1; if(r <= mid) update(l,r,v,cur<<1); else if(l > mid) update(l,r,v,cur<<1|1); else { update(l,mid,v,cur<<1); update(mid+1,r,v,cur<<1|1); } Getmax(cur);//根据左右子树的值回溯更新当前节点的值}int query(int l,int r,int cur){ if( l <= a[cur].l && r >= a[cur].r){ return a[cur]._max; }//若等于要求的区间,则返回结点保存的最值 pushdown(cur);//----延迟标志域向下传递 int mid = (a[cur].l + a[cur].r )>>1; //分别从左右子树查询,返回两者查询结果的较大值 if(r <= mid ) return query(l,r,cur<<1); else if(l > mid) return query(l,r,cur<<1|1); else { return max(query(l,mid,cur<<1),query(mid+1,r,cur<<1|1)); }}int main(){ int t; scanf("%d",&t); while(t--){ int n,m,k; scanf("%d%d%d",&n,&m,&k); for(int i = 1 ;i <= n ; i++) scanf("%d",&v[i]); mem0(b); for(int i = 1 ; i <= k ; i++) b[1]+=v[i];//第一段和,从1~k for(int i = 2 ; i <= n-k+1;i++) b[i]=b[i-1]-v[i-1]+v[i+k-1]; //求剩下每k段和,2~k+1...n-k+1~n build(1,n-k+1,1); while(m--){ int c,x,y; scanf("%d%d%d",&c,&x,&y); if(c==0){ update(max(1,x-k+1),min(n-k+1,x),y-v[x],1); v[x]=y; } else if(c== 1){ update(max(1,x-k+1),min(n-k+1,x),v[y]-v[x],1); update(max(1,y-k+1),min(n-k+1,y),v[x]-v[y],1); swap(v[x],v[y]); } else printf("%d\n",query(x,y-k+1,1)); } } return 0;}
0 0
- poj_4047Garden区间更新_求和
- hdu_1166_线段树_单点更新_区间求和
- POJ 3468(区间更新,求和)
- HDU 1698 区间更新 求和
- 线段树区间更新+求和
- hdu1166单点更新,区间求和
- 树状数组 区间更新 区间求和
- 树状数组 区间更新 区间求和
- poj3468 线段树区间更新,区间求和
- Splay解决区间问题[区间更新,区间求和]
- HDU1698(线段树区间更新求和)
- 线段树(区间更新求和)
- 线段树(单点更新,区间求和)
- pku3468----成段更新区间求和
- 线段树 (区间更新求和)
- poj2352Stars【线段树单点更新区间求和】
- 线段树单点更新 区间求和,求最值
- leetCode_线段树、单点更新、区间求和
- 工作有感——拖延与提前
- box-sizing
- String类的使用和说明
- SQL/NoSQL两大阵营激辩:谁更适合大数据
- hdu-5063 Operation the Sequence
- poj_4047Garden区间更新_求和
- hdu 3691最小割将一个图分成两部分
- HDU 3032 Lasker's Nim博弈
- 菜鸟DirectX之顶点缓存
- 苏移笔试
- HD-oj 1228
- Oracle Merge 使用
- ZOJ——3819 Average Score
- 线程生命周期