spojGSS2 1557 Can you answer these queries II(成段更新)
来源:互联网 发布:无印良品 推荐 知乎 编辑:程序博客网 时间:2024/04/29 03:27
题意:给你N个数,每个数a[i]的范围在[-100000,100000],然后有Q个查询,每个查询问区间[x,y]内最大子区间和为多少,并且重复出现的值只能计算一次(如果是负数,输出0,即可以子区间可以为空)。
离线处理查询。每个值只能计算一次的方法同之前的hdu 3333 Turing Tree & hdu 3874 Necklace (成段更新)及Codeforces Round #136 (Div. 2) D. Little Elephant and Array方法一样,不再赘述——解题报告Here。
首先,因为是离线处理,我们是从左到右处理每个a[i]的,这题线段树的每个叶子结点里存储的是,位置1,2,...,i-1,i到当前位置i的区间和sum,及最大子区间和mx。明白了这点,那么问题是如何去维护最大子区间和mx。方法是通过sum,及两个懒操作值,flag_sum和flag_mx(分别表示在更新过程中这个区间的左右子儿子区间需要加上的值,设这个值为valu,并且从flag_sum=0加到flag_sum=valu的过程中,最大值是多少——flag_mx。
其次,mx,sum,flag_mx,flag_sum的初值都应该是0(因为,子区间可以为空,即应该排除负数)。向下传递两个懒操作值的方法是:子区间的flag_mx值为,其原值、子区间的flag_sum加上当前区间的flag_mx,中取一个较大值。之后,子区间的flag_sum加上当前区间的flag_sum。
为什么这么做呢?子区间的flag_mx的最大值,除了原值,还有可能出现在,子区间的flag_sum加到子区间的flag_sum加上当前区间的flag_sum的过程中,而这个过程中的最大值显然是子区间的flag_sum加上当前区间的flag_mx。 最后如何更新mx和sum呢?
对于非叶子结点:
当前区间的sum,从子区间的sum值中取较大值,再加上当前区间的flag_sum。
当前区间的mx,1.从子区间的mx值中取较大值。2.两个子区间的sum中取较大值,
再加上当前区间的flag_mx。
对于叶子结点:
当前区间的sum值即是flag_sum,mx即是flag_mx。
为什么这么做呢?
起先想能不能用直接用当前区间变化后的flag_sum、flag_mx去更新当前区间的sum、mx。后来发现有一个问题——如果这样做,那么每次变化都要向下传递这两个懒操作值。复杂度就退化成O(N)的了,相当于懒操作值没起作用。
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <map>#include <algorithm>using namespace std;#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define MID(a,b) (a+((b-a)>>1))typedef long long LL;const int N=100005;struct OP{int st,ed,id;OP(){}OP(int a,int b,int c){st=a;ed=b;id=c;}bool operator<(const OP &b)const{ return ed<b.ed; }}op[N];struct node{int lft,rht;LL mx,sum;LL flag_mx,flag_sum;int mid(){return MID(lft,rht);}void init() { mx=sum=flag_mx=flag_sum=0; }void fun(LL a,LL b){flag_mx=max(flag_mx,flag_sum+b);flag_sum+=a;}};int n,m,pos[N*2],a[N];LL res[N];struct Segtree{node tree[N*4];void PushUp(int ind){if(tree[ind].lft!=tree[ind].rht){tree[ind].sum=max(tree[LL(ind)].sum,tree[RR(ind)].sum)+tree[ind].flag_sum;tree[ind].mx=max(tree[LL(ind)].mx,tree[RR(ind)].mx);tree[ind].mx=max(tree[ind].mx,max(tree[LL(ind)].sum,tree[RR(ind)].sum)+tree[ind].flag_mx);}else{tree[ind].sum=tree[ind].flag_sum;tree[ind].mx=tree[ind].flag_mx;}}void PushDown(int ind){LL &tmp1=tree[ind].flag_sum,&tmp2=tree[ind].flag_mx;tree[LL(ind)].fun(tmp1,tmp2); PushUp(LL(ind));tree[RR(ind)].fun(tmp1,tmp2); PushUp(RR(ind));tmp1=tmp2=0;}void build(int lft,int rht,int ind){tree[ind].lft=lft;tree[ind].rht=rht;tree[ind].init();if(lft!=rht){int mid=tree[ind].mid();build(lft,mid,LL(ind));build(mid+1,rht,RR(ind));}}void updata(int st,int ed,int ind,int valu){int lft=tree[ind].lft,rht=tree[ind].rht;if(st<=lft&&rht<=ed){tree[ind].fun(valu,valu);PushUp(ind);}else {PushDown(ind);int mid=tree[ind].mid();if(st<=mid) updata(st,ed,LL(ind),valu);if(ed >mid) updata(st,ed,RR(ind),valu);PushUp(ind);}}LL query(int st,int ed,int ind){int lft=tree[ind].lft,rht=tree[ind].rht;if(st<=lft&&rht<=ed) return tree[ind].mx;else {PushDown(ind);int mid=tree[ind].mid();LL mx1=0,mx2=0;if(st<=mid) mx1=query(st,ed,LL(ind));if(ed> mid) mx2=query(st,ed,RR(ind));//PushUp(ind);//查询未更新值,这里可以不用向上传递return max(mx1,mx2);}}}seg;int main(){while(scanf("%d",&n)!=EOF){memset(pos,0,sizeof(pos));for(int i=1;i<=n;i++) scanf("%d",&a[i]);scanf("%d",&m);for(int i=0;i<m;i++){int st,ed;scanf("%d%d",&st,&ed);op[i]=OP(st,ed,i);}sort(op,op+m);int ind=0;seg.build(1,n,1);for(int i=1;i<=n;i++){int &tmp=pos[a[i]+N];seg.updata(tmp+1,i,1,a[i]);tmp=i;while(ind<m&&op[ind].ed==i){res[op[ind].id]=seg.query(op[ind].st,op[ind].ed,1);ind++;}}for(int i=0;i<m;i++) printf("%lld\n",res[i]);}return 0;}
- spojGSS2 1557 Can you answer these queries II(成段更新)
- hdu4027 Can you answer these queries?(成段更新)
- HDU 4027 Can you answer these queries(线段树 成段更新)
- spoj 1557 Can you answer these queries II
- 【SPOJ】1557 Can you answer these queries II 线段树
- GSS2 - Can you answer these queries II(线段树)
- Can you answer these queries II 线段树(区间的区间更新)
- Can you answer these queries?(单点更新+标记)
- Can you answer these queries? (区间更新, 开根号)
- SPOJ 1557 Can you answer these queries II(GSS2 线段树)
- SPOJ 1557 Can you answer these queries II(离线处理+线段树求历史最大)
- Spoj 1557 Can you answer these queries II 线段树 任意区间最大子段和 不重复数字
- Can you answer these queries?
- Can you answer these queries?
- Can you answer these queries?
- Can you answer these queries?
- Can you answer these queries?
- Can you answer these queries?
- AT&T 汇编数据传送
- cocos2d-x CCUserDefault 无法写入数据
- ch C/C++语言解释器
- mkdosfs 建立硬盘启动扇区参数 (bs结构体 一)
- hdu 1254 推箱子
- spojGSS2 1557 Can you answer these queries II(成段更新)
- web.py 连接远程数据库方法
- python 向mysql中存储图片以及读取图片
- edit distance
- ORA-00600: internal error code, arguments: [4194], [], [], [], [], [], [], [], [], [], [], []
- web.py数据库入门
- web.py 数据库操作指南
- sae python sdk 认证指南
- Mac/Xcode