HDU 3308——LCIS(线段树,区间合并,最长连续递增子序列)
2014-09-15 13:07
603 查看
LCIS
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4255 Accepted Submission(s): 1938
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].
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).
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
—————————————————————分割线——————————————————————
题目大意:
给定一个序列,有两种操作
1:U a b 将第a个元素的值改为b(下标从0开始)
2:Q a b 查询区间[a,b]的最长连续递增子序列的长度
思路:
维护某个节点区间的 左连续递增区间长度,右连续递增区间长度,总的连续递增区间长度
然后简单的查询 左、中、右 具有相同的优先级
因为修改为单点修改,因此要更新到叶子节点,push_up
虽然自己知道思路,打来打去小细节害死人啊
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn=100001; using namespace std; int lc[maxn<<2],rc[maxn<<2],mc[maxn<<2]; int lnum[maxn<<2],rnum[maxn<<2]; void push_up(int rt,int m) { lnum[rt]=lnum[rt<<1]; rnum[rt]=rnum[rt<<1|1]; lc[rt]=lc[rt<<1]; rc[rt]=rc[rt<<1|1]; mc[rt]=max(mc[rt<<1],mc[rt<<1|1]); if(rnum[rt<<1]<lnum[rt<<1|1]){ if(lc[rt]==(m-(m>>1))) lc[rt]+=lc[rt<<1|1]; if(rc[rt]==(m>>1)) rc[rt]+=rc[rt<<1]; mc[rt]=max(lc[rt<<1|1]+rc[rt<<1],mc[rt]); } } void build(int l,int r,int rt) { if(l==r){ scanf("%d",&lnum[rt]); rnum[rt]=lnum[rt]; mc[rt]=lc[rt]=rc[rt]=1; return ; } int m=(l+r)>>1; build(lson); build(rson); push_up(rt,r-l+1); } void update(int p,int modify,int l,int r,int rt) { if(l==r){ lnum[rt]=rnum[rt]=modify; return ; } int m=(l+r)>>1; if(p<=m) update(p,modify,lson); else update(p,modify,rson); push_up(rt,r-l+1); } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R){ return mc[rt]; } int m=(l+r)>>1; int maxx=0; if(L<=m) maxx=max(maxx,query(L,R,lson)); if(m<R) maxx=max(maxx,query(L,R,rson)); if(rnum[rt<<1]<lnum[rt<<1|1]) maxx=max(maxx,min(m-L+1,rc[rt<<1])+min(R-m,lc[rt<<1|1])); return maxx; } int main() { int T,n,m; cin>>T; while(T--){ scanf("%d %d",&n,&m); build(0,n-1,1); char op[2];int a,b; while(m--){ scanf("%s %d %d",op,&a,&b); if(op[0]=='U') update(a,b,0,n-1,1); else printf("%d\n",query(a,b,0,n-1,1)); } } return 0; }
相关文章推荐
- 线段树区间合并+最长连续递增子序列——HDU 3308
- HDU 3308 LCIS(线段树+区间合并+最长递增连续子串)
- HDU 3308 LCIS(最长连续上升子序列)(线段树区间合并)
- hdu 3308 LCIS 最大连续递增字串长 线段树区间合并
- HDU 3308 LCIS 最长上升字串(线段树区间合并)
- hdu 3308 LCIS(线段树 最长连续递增)
- HDU 3308 LCIS 最长连续递增序列+数据结构+线段树+单点更新
- hdu 3308 线段树-区间连续最长上升子序列
- HDU 3308 线段树单点更新+区间查找最长连续子序列
- hdoj 3308 LCIS 【线段树单点更新 + 区间合并】【求解最长递增序列 的长度】
- 【HDU】3308 LCIS (线段树-区间合并)
- HDU - 3308 - LCIS (线段树 - 区间合并)
- HDU 3308 LCIS (线段树区间合并)
- hdu 3308 LCIS(线段树区间合并)
- HDU 3308 线段树 最长连续上升子序列 单点更新 区间查询
- HDU 3308 线段树 最长连续上升子序列 单点更新 区间查询
- HDU 3308 LCIS (线段树区间合并)
- HDU 3308 LCIS(线段树区间合并)
- HDU 3308 LCIS 线段树 区间合并 入门题
- HDU 3308 - LCIS(线段树+区间合并)