【线段树】HDU 3308 LCIS
= =
两种操作:
U A B:将A位置更新为B
Q A B:求A-B区间内的最长连续上升子序列的长度
需要四个数组
用num 表示序列
用sum 表示该储存该子树的最长连续上升子序列的长度
用lsum 表示该储存该子树的从子树的第一个num开始的最长连续上升子序列的长度
rsum则表示从结束于该子树最后一个num的最长连续上升子序列的长度
更新操作只需要单点更新即可
在pushup时
rt节点的lsum继承了左子节点的lsum
rt节点的rsum继承了右子节点的rsum
rt的sum则需要取左右子节点的sum最大值以及比较两子节点下的num可能连续形成新的上升序列;
同样查询操作时同样是取左右子节点的最大值和可能形成新的子序列;
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> using namespace std; #include <queue> #include <stack> #include <vector> #include <deque> #include <set> #include <map> #define IN freopen ("in.txt" , "r" , stdin); #define OUT freopen ("out.txt" , "w" , stdout); typedef long long LL; const int MAXN = 100110;//点数的最大值 const int MAXM = 20006;//边数的最大值 const int INF = 11521204; const int mod=1000000007; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int num[MAXN]; int sum[MAXN<<2],lsum[MAXN<<2],rsum[MAXN<<2]; int col[MAXN<<2]; void pushup(int rt,int m,int l) { int lx=m-(m>>1); int rx=(m>>1); lsum[rt]=lsum[rt<<1]; rsum[rt]=rsum[rt<<1|1]; if(lsum[rt]==lx&&num[lx+l-1]<num[lx+l]) lsum[rt]+=lsum[rt<<1|1]; if(rsum[rt]==rx&&num[lx+l-1]<num[lx+l]) rsum[rt]+=rsum[rt<<1]; sum[rt]=max(max(sum[rt<<1],sum[rt<<1|1]),num[lx+l-1]<num[lx+l]?rsum[rt<<1]+lsum[rt<<1|1]:0); } void build(int l,int r,int rt) { col[rt]=0; if(l==r) { scanf("%d",&num[l]); sum[rt]=lsum[rt]=rsum[rt]=1; return ; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt,r-l+1,l); } void update(int x,int cc,int l,int r,int rt) { if(l==r) { num[l]=cc; return ; } int m=(l+r)>>1; if(x<=m) update(x,cc,lson); else update(x,cc,rson); pushup(rt,r-l+1,l); } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { return sum[rt]; } int m=(l+r)>>1,res=0; if(L<=m) res=max(res, query(L,R,lson)); if(m<R) res=max(res,query(L,R,rson)); if (num[m] < num[m+1]) res = max(res, min(m-L+1, rsum[rt<<1])+min(R-m, lsum[rt<<1|1])); return res; } int main() { int n,m,t; IN; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); build(1,n,1); while(m--) { char c[2]; int a,b; scanf("%s%d%d",c,&a,&b); if(c[0]=='U') update(a+1,b,1,n,1); else printf("%d\n",query(a+1,b+1,1,n,1)); } } return 0; }