Time Limit: 2000MS | Memory Limit: 32768KB | 64bit IO Format: %I64d & %I64u |
Description
Given n integers.
You have two operations:
U A B: replace the Ath number by B. (index counting from 0)
Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b].
You have two operations:
U A B: replace the Ath number by B. (index counting from 0)
Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b].
Input
T in the first line, indicating the case number.
Each case starts with two integers n , m(0<n,m<=10 5).
The next line has n integers(0<=val<=10 5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10 5)
OR
Q A B(0<=A<=B< n).
Each case starts with two integers n , m(0<n,m<=10 5).
The next line has n integers(0<=val<=10 5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10 5)
OR
Q A B(0<=A<=B< n).
Output
For each Q, output the answer.
Sample Input
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
Sample Output
1
1
4
2
3
1
2
5
Source
线段树维护每个区间的三个值:从左开始数的最长单调上升序列,本区间内最长答案,以最右为结尾的最长单调上升序列。
每次合并的时候,如果左子树的右端点的值小于右子树的左端点的值,那么两段序列可以接起来……
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define ls l,mid,rt<<1 7 #define rs mid+1,r,rt<<1|1 8 using namespace std; 9 const int mxn=100010; 10 int n,m; 11 int d[mxn]; 12 struct node{ 13 int cnt;int lans,rans; 14 }t[mxn<<2]; 15 void update(int p,int l,int r,int rt){ 16 if(l==r)return; 17 int mid=(l+r)>>1; 18 if(p<=mid)update(p,ls); 19 else update(p,rs); 20 t[rt].cnt=max(t[rt<<1].cnt,t[rt<<1|1].cnt); 21 t[rt].lans=t[rt<<1].lans;t[rt].rans=t[rt<<1|1].rans; 22 if(d[mid]<d[mid+1]){ 23 t[rt].cnt=max(t[rt].cnt,t[rt<<1].rans+t[rt<<1|1].lans); 24 if(t[rt<<1].lans==mid-l+1) 25 t[rt].lans=t[rt<<1].lans+t[rt<<1|1].lans; 26 if(t[rt<<1|1].rans==r-mid) 27 t[rt].rans=t[rt<<1|1].rans+t[rt<<1].rans; 28 } 29 return; 30 } 31 void Build(int l,int r,int rt){ 32 if(l==r){ 33 t[rt].cnt=t[rt].lans=t[rt].rans=1; 34 return; 35 } 36 int mid=(l+r)>>1; 37 Build(ls); 38 Build(rs); 39 t[rt].cnt=max(t[rt<<1].cnt,t[rt<<1|1].cnt); 40 t[rt].lans=t[rt<<1].lans; 41 t[rt].rans=t[rt<<1|1].rans; 42 if(d[mid]<d[mid+1]){ 43 t[rt].cnt=max(t[rt].cnt,t[rt<<1].rans+t[rt<<1|1].lans); 44 if(t[rt<<1].lans==mid-l+1) 45 t[rt].lans=t[rt<<1].lans+t[rt<<1|1].lans; 46 if(t[rt<<1|1].rans==r-mid) 47 t[rt].rans=t[rt<<1|1].rans+t[rt<<1].rans; 48 } 49 return; 50 } 51 int query(int L,int R,int l,int r,int rt){ 52 if(L<=l && r<=R) return t[rt].cnt; 53 int mid=(l+r)>>1; 54 if(R<=mid)return query(L,R,ls); 55 if(mid<L)return query(L,R,rs); 56 else{ 57 int res=max(query(L,R,ls),query(L,R,rs)); 58 if(d[mid]<d[mid+1]){//如果结点所存答案长于区间长度,实际答案等于区间长度,用min维护 59 res=max(res,(min(t[rt<<1].rans,mid-L+1)+min(t[rt<<1|1].lans,R-mid))); 60 } 61 return res; 62 } 63 } 64 int main(){ 65 int T; 66 scanf("%d",&T); 67 while(T--){ 68 memset(t,0,sizeof 0); 69 int i,j; 70 scanf("%d%d",&n,&m); 71 for(i=1;i<=n;i++)scanf("%d",&d[i]); 72 Build(1,n,1); 73 char op[2];int a,b; 74 for(i=1;i<=m;i++){ 75 scanf("%s%d%d",op,&a,&b); 76 if(op[0]=='U'){ 77 d[++a]=b; 78 update(a,1,n,1); 79 } 80 if(op[0]=='Q'){ 81 82 printf("%d ",query(a+1,b+1,1,n,1)); 83 } 84 } 85 } 86 return 0; 87 }