vijos p1659——河蟹王国(线段树)(复习)
描述
河蟹王国有一位河蟹国王,他的名字叫羊驼。河蟹王国富饶安定,人们和谐相处。有一天,羊驼国王心血来潮,想在一部分人中挑出最和谐的人。于是,羊驼国王将他的子民排成了一列(==!!b汗~好长呀)。每个人都有一个初始的和谐值。羊驼国王每次会选择一个区间[L,R],这个区间中和谐值最大的人就是国王选出的人。而且,在某一时间,区间[L',R']里的人会变得熟悉,因此他们每个人的和谐值都会上升一个相同的值C。羊驼国王想知道,对于每一次选择,他选出的最大和谐值是多少。
格式
输入格式
第一行是一个数N(1<=N<=100000),表示人数。
接下来的N行,每行一个数,表示排成的序列第i个人和谐值的初始值。
接下来是一个数M(1<=M<=100000),表示羊驼国王或他的子民有所活动(羊驼国王选择一个区间算一次,某区间里的人增长和谐值算一次)的总次数。
接下来的M行,每行第一个是一个数K,K是1或2,若K=1,接下来有三个数L,R,C,表示区间[L,R]的所有人增加C的和谐值;若K=2,接下来有两个数L,R,表示国王选择了区间[L,R]。
输出格式
每次对于国王选择区间,输出选择区间里的最大和谐值。
限制
每个测试点1s。
提示
保证所有的数以及结果都在longint范围内。
区间更改,区间查询——线段树/树状数组
这里用的线段树,注意结构体中还要有一个add,表示增加量。在更新操作中,注意:当查询到区间匹配时,区间最大值直接加上输入的增量,用add传递下去再pushup。传递add就pushdown。一定要深刻理解up和down的用法。
居然没有区间和,总觉得写起来怪怪的。。。
还发现了一个很诡异的东西,当查询写成int函数时,不会超时。但当写成void函数时要超时4组,加上inline后才不会超时。。。
祝自己NOIP顺利~
#include<bits/stdc++.h> using namespace std; #define L(u) (u*2) #define R(u) (u*2+1) const int maxn=1000005; int a[maxn]; struct node{ int l,r,maxnum,add; }w[maxn]; int n,m;int ans=0; inline void pushup(int u) { w[u].maxnum=max(w[L(u)].maxnum,w[R(u)].maxnum); return ; } inline void pushdown(int u) { w[L(u)].add+=w[u].add; w[L(u)].maxnum+=w[u].add; w[R(u)].add+=w[u].add; w[R(u)].maxnum+=w[u].add; w[u].add=0; return ; } inline void buildtree(int u,int left,int right) { w[u].l=left;w[u].r=right; if(left==right) { w[u].maxnum=a[left]; return ; } int mid=(left+right)>>1; buildtree(L(u),left,mid); buildtree(R(u),mid+1,right); pushup(u); } inline void findans(int u,int left,int right) { if(w[u].l==left&&w[u].r==right) { ans=max(ans,w[u].maxnum); return ; } if(w[u].add!=0)pushdown(u); int mid=(w[u].l+w[u].r)>>1; if(left>=mid+1) findans(R(u),left,right); else if(right<=mid) findans(L(u),left,right); else { findans(L(u),left,mid); findans(R(u),mid+1,right); } return ; } inline void update(int u,int left,int right,int val) { if(w[u].l==left&&w[u].r==right) { w[u].maxnum+=val; w[u].add+=val; return ; } if(w[u].add!=0)pushdown(u); int mid=(w[u].l+w[u].r)>>1; if(left>=mid+1) update(R(u),left,right,val); else if(right<=mid) update(L(u),left,right,val); else { update(L(u),left,mid,val); update(R(u),mid+1,right,val); } pushup(u); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); buildtree(1,1,n); scanf("%d",&m); for(int i=1;i<=m;i++) { int q;scanf("%d",&q); if(q==1) { int x,y,z; scanf("%d%d%d",&x,&y,&z); update(1,x,y,z); continue; } else { int x,y; scanf("%d%d",&x,&y); ans=-100000000; findans(1,x,y); printf("%d\n",ans); continue; } } return 0; }