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].
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).
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
没思路,Orz 一下大佬们。
解看代码吧。
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)
const int MAXN = 1e5+10;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
struct Tree{
int l, r, len;//区间左右端点 和 长度
int lv, rv;//区间左端点的值 右端点的值
int lsum, rsum;//以区间左端点为起点的最长递增序列长度 以区间右端点为终点的最长递增序列长度
int sum;//区间 最长递增序列长度
}tree[MAXN<<2];
void Up(int o){
tree[o].lv=tree[o<<1].lv;
tree[o].rv=tree[o<<1|1].rv;
tree[o].lsum=tree[o<<1].lsum;
tree[o].rsum=tree[o<<1|1].rsum;
tree[o].sum=max(tree[o<<1].sum,tree[o<<1|1].sum);
if(tree[o<<1].rv<tree[o<<1|1].lv){
if(tree[o<<1].lsum==tree[o<<1].len) //左半区间完全容纳最长递增序列 向右延伸
tree[o].lsum+=tree[o<<1|1].lsum;
if(tree[o<<1|1].rsum==tree[o<<1|1].len) //右半区间完全容纳最长递增序列 向左延伸
tree[o].rsum+=tree[o<<1].rsum;
tree[o].sum=max(tree[o].sum,max(tree[o].lsum,tree[o].rsum)); //更新
tree[o].sum=max(tree[o].sum,tree[o<<1].rsum+tree[o<<1|1].lsum);
}
}
void Build(int o,int le,int ri){
tree[o].l=le;tree[o].r=ri;tree[o].len=ri-le+1;
if(le==ri){
int val;scanf("%d",&val);
tree[o].lv=tree[o].rv=val;
tree[o].lsum=tree[o].rsum=tree[o].sum=1;
return ;
}
int mid=(tree[o].l+tree[o].r)>>1;
Build(o<<1,le,mid);
Build(o<<1|1,mid+1,ri);
Up(o);
}
void UpDate(int o,int pos,int val){
if(tree[o].l==tree[o].r){
tree[o].lv=tree[o].rv=val;
return ;
}
int mid=(tree[o].l+tree[o].r)>>1;
if(pos<=mid) UpDate(o<<1,pos,val);
else UpDate(o<<1|1,pos,val);
Up(o);
}
int Query(int o,int le,int ri){
if(le<=tree[o].l&&tree[o].r<=ri) {
return tree[o].sum;
}
int mid=(tree[o].l+tree[o].r)>>1;
if(ri<=mid) return Query(o<<1,le,ri);
else if(le>mid) return Query(o<<1|1,le,ri);
else {
int a=Query(o<<1,le,mid);
int b=Query(o<<1|1,mid+1,ri);
int ans=max(a,b);
if(tree[o<<1].rv<tree[o<<1|1].lv) { // 不在区间里的话,会查询两个部分的最大值,
//但是其实这两个部分是连着的,所以有的这里的代码
ans=max(ans,min(tree[o<<1].rsum,mid-le+1)+min(tree[o<<1|1].lsum,ri-mid));
}
return ans;
}
}
int main(){
CLOSE();
// fread();
// fwrite();
int T;scanf("%d",&T);
while(T--){
int n,q;
scanf("%d%d",&n,&q);
Build(1,0,n-1);
char op[5];
while(q--){
int a,b;
scanf("%s%d%d",op,&a,&b);
if(op[0]=='U') UpDate(1,a,b);
else printf("%d\n",Query(1,a,b));
}
}
return 0;
}