For a sequence S1,S2,...,SN, and a pair of integers (i, j), if 1 <= i <= j <= N and Si < Si+1 < Si+2 <...< Sj-1 < Sj, then the sequence Si,Si+1,...,Sj is a CIS (Continuous Increasing Subsequence). The longest CIS of a sequence is called the LCIS (Longest Continuous Increasing Subsequence).
In this problem, we will give you a sequence first, and then some “add” operations and some “query” operations. An add operation adds a value to each member in a specified interval. For a query operation, you should output the length of the LCIS of a specified interval.
The first line of the input is an integer T, which stands for the number of test cases you need to solve.
Every test case begins with two integers N, Q, where N is the size of the sequence, and Q is the number of queries. S1,S2,...,SNare specified on the next line, and then Q queries follow. Every query begins with a character ‘a’ or ‘q’. ‘a’ is followed by three integers L, R, V, meaning that add V to members in the interval [L, R] (including L, R), and ‘q’ is followed by two integers L, R, meaning that you should output the length of the LCIS of interval [L, R].
For every test case, you should output "Case #k:" on a single line first, where k indicates the case number and starts at 1. Then for every ‘q’ query, output the answer on a single line. See sample for more details.
1
5 6
0 1 2 3 4
q 1 4
a 1 2 -10
a 1 1 -6
a 5 5 -4
q 2 3
q 4 4
Case #1:
4
2
1
The 9th UESTC Programming Contest Preliminary
题目:http://acm.uestc.edu.cn/problem.php?pid=1425
题意:给你一个数列,每次回选择一个区间的数,或者把这些数都加上一个值,或者问你这些数的最长递增序列。。。
分析:这题对区间进行操作,很容易使我们想到线段树,但是,线段树要保存那些信息才能求得答案呢,成段的累加这个不是问题,只要加个延迟标记就行,最主要的是询问最长递增序列。。。
1.当然,我们肯定要保存区间的最大值,每次向上更新时,理首当然的取左右子树的最大值。。。但是如果两个区间合并出更长的序列呢?
2.保存每个区间左右边界的值,这个方便我们判断两个区间是否能合并,这样向上更新时就能知道是否会出现更优值了。。。
3.知道可能合并,那我们怎么求出现的更优值呢,当然,它会出现在中间,我们需要知道从左线段的右端可以到达的最左端 lmost,和右线段左端能到达的最右端rmost ,新的值就是 rmost-lmost+1,所以我们要保存所有线段左端点能到达的最右端,右端点能到达的最左端。。。。也就是lmost ,rmost
具体的实现看代码吧
代码:
#include<cstdio> #include<iostream> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int mm=111111; int dly[mm<<2],maxlen[mm<<2],vall[mm<<2],valr[mm<<2],rmost[mm<<2],lmost[mm<<2]; void add(int rt,int val) { vall[rt]+=val,valr[rt]+=val; } void pushdown(int rt) { add(rt<<1,dly[rt]),add(rt<<1|1,dly[rt]); dly[rt<<1]+=dly[rt],dly[rt<<1|1]+=dly[rt]; dly[rt]=0; } void pushup(int rt,int m) { maxlen[rt]=max(maxlen[rt<<1],maxlen[rt<<1|1]); vall[rt]=vall[rt<<1],valr[rt]=valr[rt<<1|1]; rmost[rt]=rmost[rt<<1],lmost[rt]=lmost[rt<<1|1]; if(valr[rt<<1]<vall[rt<<1|1]) { maxlen[rt]=max(maxlen[rt],rmost[rt<<1|1]-lmost[rt<<1]+1); if(rmost[rt]>=m)rmost[rt]=rmost[rt<<1|1]; if(lmost[rt]<=m+1)lmost[rt]=lmost[rt<<1]; } } void build(int l,int r,int rt) { dly[rt]=0; if(l==r) { scanf("%d",&vall[rt]); valr[rt]=vall[rt]; rmost[rt]=r,lmost[rt]=l,maxlen[rt]=1; return; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt,m); } void updata(int L,int R,int val,int l,int r,int rt) { if(L<=l&&R>=r) { add(rt,val); dly[rt]+=val; return; } int m=(l+r)>>1; if(dly[rt])pushdown(rt); if(L<=m)updata(L,R,val,lson); if(R>m)updata(L,R,val,rson); pushup(rt,m); } int query(int L,int R,int l,int r,int rt) { if(L<=l&&R>=r)return maxlen[rt]; int m=(l+r)>>1; if(R<=m)return query(L,R,lson); if(L>m)return query(L,R,rson); int ret=max(query(L,R,lson),query(L,R,rson)); if(valr[rt<<1]<vall[rt<<1|1])ret=max(ret,min(R,rmost[rt<<1|1])-max(L,lmost[rt<<1])+1); return ret; } int main() { int i,j,k,n,m,t,cs; char op[55]; scanf("%d",&t); for(cs=1;cs<=t;++cs) { scanf("%d%d",&n,&m); build(1,n,1); printf("Case #%d:\n",cs); while(m--) { scanf("%s%d%d",op,&i,&j); if(op[0]=='q')printf("%d\n",query(i,j,1,n,1)); else { scanf("%d",&k); updata(i,j,k,1,n,1); } } } return 0; }