hdu 3308 线段树-区间连续最长上升子序列
2015-05-01 13:40
411 查看
LCIS
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4842 Accepted Submission(s): 2166
[align=left]Problem Description[/align]
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].
[align=left]Input[/align]
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).
[align=left]Output[/align]
For each Q, output the answer.
[align=left]Sample Input[/align]
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
[align=left]Sample Output[/align]
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;
}
相关文章推荐
- HDU 3308 LCIS(最长连续上升子序列)(线段树区间合并)
- HDU 3308 线段树。。最长连续上升子序列
- HDU 3308 线段树 最长连续上升子序列 单点更新 区间查询
- HDU 3308 线段树 最长连续上升子序列 单点更新 区间查询
- HDU 3308 线段树单点更新+区间查找最长连续子序列
- HDU 3308——LCIS(线段树,区间合并,最长连续递增子序列)
- 线段树区间合并+最长连续递增子序列——HDU 3308
- HDU 3308【线段树-query:区间最长单调上升序列,update:结点更新,区间合并】
- HDU 3308 最长上升连续子序列 (线段树)
- HDU 3308 LCIS(最长连续上升子序列)
- hdu 3308 最长连续上升区间
- hdu 3308 最长连续上升区间
- HDU 3308 LCIS(线段树+区间合并+最长递增连续子串)
- HDU 3308 LCIS 最长上升字串(线段树区间合并)
- 【维护区间最长连续子序列 && 线段树 && 区间归并】HDU - 1540 Tunnel Warfare
- hdu3308 LCIS--区间更新 & 最长连续上升子序列
- hdu 3308 LCIS 最大连续递增字串长 线段树区间合并
- HDU 3308 LCIS 最长连续递增序列+数据结构+线段树+单点更新
- HDU-4553-约会安排(线段树维护最长连续区间)
- hdu 3308 LCIS(线段树 最长连续递增)