LCIS
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4842 Accepted Submission(s): 2166
Problem 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<=105).
The next line has n integers(0<=val<=105).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=105)
OR
Q A B(0<=A<=B< n).
Each case starts with two integers n , m(0<n,m<=105).
The next line has n integers(0<=val<=105).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=105)
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
求区间连续最长子序列,用线段树分治的思想做。某个区间的[l,r]的最长子序列,将区间分解成两部分,最长部分可能在[l,m]、[m+1,r]、或者部分在左半部部分在右半部份。
对于第三种情况,其长度为左半部分的右端点开始逆向的最长下降长度+右半部份的左端点为起点的最长上升长度(前提a[m]<a[m+1])。
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std;
#define maxn 300005
#define getc int m=(l+r)>>1, lc=rt<<1,rc=rt<<1|1
int lk[maxn],rk[maxn],ls[maxn],rs[maxn],s[maxn];
int a[maxn/3];
void push_up(int rt, int l, int r)
{
getc;
lk[rt]=lk[lc],rk[rt]=rk[rc];
s[rt]=max(s[lc], s[rc]);
if(rk[lc]<lk[rc])
s[rt]=max(s[rt], rs[lc]+ls[rc]);
ls[rt]=ls[lc];
if(ls[lc]==m-l+1 && rk[lc]<lk[rc])
ls[rt]=ls[lc]+ls[rc];
rs[rt]=rs[rc];
if(rs[rc]==r-m && rk[lc]<lk[rc])
rs[rt]=rs[rc]+rs[lc];
}
void build(int rt, int l, int r)
{
if(l==r){
lk[rt]=rk[rt]=a[l];
s[rt]=ls[rt]=rs[rt]=1;
return;
}
getc;
build(lc, l, m);
build(rc, m+1, r);
push_up(rt, l, r);
}
void update(int rt, int l, int r, int k, int v)
{
if(l==r){
lk[rt]=rk[rt]=v;
s[rt]=ls[rt]=rs[rt]=1;
return;
}
getc;
if(k<=m)
update(lc, l, m, k, v);
else
update(rc, m+1, r, k, v);
push_up(rt, l, r);
}
int lquery(int rt, int l, int r, int ll, int rr)
{
if(ll<=l && r<=rr){
return ls[rt];
}
getc;
int ret=lquery(lc, l, m, ll, min(rr, m));
if(rr>m && ret==m-l+1 && rk[lc]<lk[rc])
ret+=lquery(rc, m+1, r, m+1, rr);
return ret;
}
int rquery(int rt, int l, int r, int ll, int rr)
{
if(ll<=l && r<=rr){
return rs[rt];
}
getc;
int ret=rquery(rc, m+1, r, max(ll, m+1), rr);
if(ll<=m && ret==r-m && rk[lc]<lk[rc])
ret+=rquery(lc, l, m, ll, m);
return ret;
}
int query(int rt, int l, int r, int ll, int rr)
{
if(ll<=l && r<=rr){
return s[rt];
}
getc;
if(rr<=m)
return query(lc, l, m, ll, rr);
else if(ll>m)
return query(rc, m+1, r, ll, rr);
else{
int ret=max(query(lc, l, m, ll, m), query(rc, m+1, r, m+1, rr));
if(rk[lc]<lk[rc])
ret=max(ret, rquery(lc, l, m, ll, m)+lquery(rc, m+1, r, m+1, rr));
return ret;
}
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
int n,m;
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++)
scanf("%d", a+i);
build(1, 1, n);
char s[3];
int a,b;
while(m--){
scanf("%s%d%d", s, &a,&b);
a++;
if(s[0]=='U'){
update(1, 1,n, a, b);
}
else{
b++;
printf("%d\n", query(1, 1, n, a,b));
}
}
}
return 0;
}