1 10 10 7 7 3 3 5 9 9 8 1 8 Q 6 6 U 3 4 Q 0 1 Q 0 5 Q 4 7 Q 3 5 Q 0 2 Q 4 6 U 6 10 Q 0 9
1 1 4 2 3 1 2 5
题意:
给你个长度为n的数组。然后可以进行两种操作。
1.U a b。把数组第a个数变为b。
2 Q a b。询问[a,b]里最长的连续递增序列的长度。
思路:
很简单。处理有点类似于hotel。维护左连续和右连续。只是注意中间连接时必须保证val[mid+1]>val[mid]。
#include<algorithm> #include<iostream> #include<string.h> #include<sstream> #include<stdio.h> #include<math.h> #include<vector> #include<string> #include<queue> #include<set> #include<map> using namespace std; const int INF=0x3f3f3f3f; const int maxn=100010; int ml[maxn<<2],mr[maxn<<2],ma[maxn<<2]; int val[maxn]; void pushup(int L,int R,int k) { int ls,rs,mid; ls=k<<1; rs=ls|1; mid=(L+R)>>1; ma[k]=max(ma[ls],ma[rs]); ml[k]=ml[ls]; mr[k]=mr[rs]; if(val[mid+1]>val[mid]) { if(ml[ls]==mid-L+1) ml[k]+=ml[rs]; if(mr[rs]==R-mid) mr[k]+=mr[ls]; ma[k]=max(ma[k],mr[ls]+ml[rs]); } } void btree(int L,int R,int k) { int ls,rs,mid; if(L==R) { scanf("%d",&val[L]); ml[k]=mr[k]=ma[k]=1; return; } ls=k<<1; rs=ls|1; mid=(L+R)>>1; btree(L,mid,ls); btree(mid+1,R,rs); pushup(L,R,k); } void update(int L,int R,int p,int k,int d) { int ls,rs,mid; if(L==R) { val[L]=d; return; } ls=k<<1; rs=ls|1; mid=(L+R)>>1; if(p>mid) update(mid+1,R,p,rs,d); else update(L,mid,p,ls,d); pushup(L,R,k); } int qu(int L,int R,int l,int r,int k) { int ls,rs,mid,a,b,ans; if(l==L&&r==R) return ma[k]; ls=k<<1; rs=ls|1; mid=(L+R)>>1; if(l>mid) return qu(mid+1,R,l,r,rs); else if(r<=mid) return qu(L,mid,l,r,ls); else { ans=max(qu(L,mid,l,mid,ls),qu(mid+1,R,mid+1,r,rs)); if(val[mid+1]>val[mid]) { a=min(mid-l+1,mr[ls]);//注意下这就行了。 b=min(r-mid,ml[rs]); return max(ans,a+b); } return ans; } } int main() { int t,n,m,a,b; char com[10]; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); btree(1,n,1); while(m--) { scanf("%s%d%d",com,&a,&b); if(com[0]=='U') { a++; update(1,n,a,1,b); } else { a++,b++; printf("%d\n",qu(1,n,a,b,1)); } } } return 0; }