题意:有T(t<10)组数据,给你N个数,M个操作(N和M都小于100000)。操作有两种类型,(1)“q a b”,查询区间[a,b]里的最长连续上升序列的长度。(2)“a l r v”,将区间[l,r]里的数全部增加v。
要记录区间里的最长的序列长度是多少,用mx来记录。由于最长的连续上升序列可以在区间的左端点,右端点,所以在线段树里增加两个域lmx和rmx,分别表示,在区间的端点处,分别向右向左的最长的满足条件的序列长度。但是还有可能出现在中间,所以又增加两个域lval和rval,分别表示区间端点的值是多少。合并的时候,判断左儿子的rval是否小于右儿子lval,如果满足,这个区间的mx可能为左儿子的rmx加上右儿子的lmx。另外,这个区间的mx可能是左儿子的mx或者右儿子的mx。
在更新当前区间的lmx时,如果左子区间的lmx等于左子区间的长度,那么当前区间的lmx就要加上右儿子的lmx。更新当前区间的rmx时同理。
另外在查询的时候,要注意,有可能当前区间的lmx大于mid-st+1,所以要在其中取一个较小值,同理rmx有可能大于ed-mid。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) const int N=100005; struct node { int lft,rht; int lmx,rmx,mx; int lval,rval,add; void fun(int tmp) { add+=tmp; lval+=tmp; rval+=tmp; } int len(){return rht-lft+1;} int mid(){return MID(lft,rht);} void init(){ lmx=rmx=mx=add=0; } }; int y[N],n,m; struct Segtree { node tree[N*4]; void down(int ind) { if(tree[ind].add) { tree[LL(ind)].fun(tree[ind].add); tree[RR(ind)].fun(tree[ind].add); tree[ind].add=0; } } void up(int ind) { tree[ind].lmx=tree[LL(ind)].lmx; tree[ind].rmx=tree[RR(ind)].rmx; tree[ind].lval=tree[LL(ind)].lval; tree[ind].rval=tree[RR(ind)].rval; tree[ind].mx=max(tree[LL(ind)].mx,tree[RR(ind)].mx); if(tree[LL(ind)].rval<tree[RR(ind)].lval) { if(tree[LL(ind)].lmx==tree[LL(ind)].len()) tree[ind].lmx+=tree[RR(ind)].lmx; if(tree[RR(ind)].rmx==tree[RR(ind)].len()) tree[ind].rmx+=tree[LL(ind)].rmx; tree[ind].mx=max(tree[ind].mx,tree[LL(ind)].rmx+tree[RR(ind)].lmx); } tree[ind].mx=max(tree[ind].mx,max(tree[ind].lmx,tree[ind].rmx)); } void build(int lft,int rht,int ind) { tree[ind].lft=lft; tree[ind].rht=rht; tree[ind].init(); if(lft==rht) { tree[ind].lval=tree[ind].rval=y[lft]; tree[ind].lmx=tree[ind].rmx=tree[ind].mx=1; } else { int mid=tree[ind].mid(); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); up(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); else { down(ind); int mid=tree[ind].mid(); if(st<=mid) updata(st,ed,LL(ind),valu); if(ed> mid) updata(st,ed,RR(ind),valu); up(ind); } } int 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 { down(ind); int mid=tree[ind].mid(); if(ed<=mid) return query(st,ed,LL(ind)); else if(st>mid) return query(st,ed,RR(ind)); else { int mid=tree[ind].mid(); int mx1=query(st,ed,LL(ind)); int mx2=query(st,ed,RR(ind)); int tmp1=0,tmp2=0; if(tree[LL(ind)].rval<tree[RR(ind)].lval) { tmp1=min(mid-st+1,tree[LL(ind)].rmx); tmp2=min(ed-mid,tree[RR(ind)].lmx); } return max(max(mx1,mx2),tmp1+tmp2); } } } }seg; int main() { int t,t_cnt=0; scanf("%d",&t); while(t--) { char str[10]; int a,b,c; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&y[i]); seg.build(1,n,1); printf("Case #%d:\n",++t_cnt); while(m--) { scanf("%s",str); if(str[0]=='q') { scanf("%d%d",&a,&b); printf("%d\n",seg.query(a,b,1)); } else { scanf("%d%d%d",&a,&b,&c); seg.updata(a,b,1,c); } } } return 0; }