(中等) 线段树 HDU 3308 LCIS

来源:互联网 发布:网络购票岫岩到沈阳 编辑:程序博客网 时间:2024/06/05 05:10

LCIS

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3082    Accepted Submission(s): 1357


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
110 107 7 3 3 5 9 9 8 1 8 Q 6 6U 3 4Q 0 1Q 0 5Q 4 7Q 3 5Q 0 2Q 4 6U 6 10Q 0 9
 

Sample Output
11423125
 

Author
shǎ崽
 

Source
HDOJ Monthly Contest – 2010.02.06
 

Recommend
wxl
 

题意:给一个数字的序列,对其若干进行单个元素修改,询问[L,R]中递增的连续的最长序列的长度。
思路:很明显是线段树的题目,对于一个区间[L,R] 用sum[rt] 表示该区间最长的递增序列 。
 对于一个根,它的最长的序列可能来自:
1.两个儿子中最大的sum
2.(如果左儿子右端点小与右儿子左端点)从左儿子的右端点与右儿子的左端点,扩展出最长递增序列。
于是加入了ins_l[] 和 ins_r[]  分别表示以该区间的左端点为起点开始最长递增序列的终点和以该区间的右端点为终点,最长递增序列的起点


代码:
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<string>
#include<deque>
#include<queue>
#include<math.h>
#include<vector>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define MAX 100000+10
#define MOD 99997
const int inf = 0xfffffff;
#define lson l , m , rt<<1
#define rson m+1 , r , rt<<1|1

int ins_l[MAX<<2];
int ins_r[MAX<<2];
int sum[MAX<<2];
int val[MAX];

void PushUp(int rt,int l,int r)
{
int m = (l+r)>>1;
if (val[m] < val[m+1])
{
sum[rt] = ins_l[rt<<1|1]-ins_r[rt<<1]+1;
if (ins_l[rt<<1]==m)
ins_l[rt] = ins_l[rt<<1|1];
else 
ins_l[rt] = ins_l[rt<<1];
if (ins_r[rt<<1|1]==m+1)
ins_r[rt] = ins_r[rt<<1];
else 
ins_r[rt] = ins_r[rt<<1|1];
sum[rt] = max(sum[rt],max(sum[rt<<1],sum[rt<<1|1]));
}
else 
{
ins_l[rt] = ins_l[rt<<1];
ins_r[rt] = ins_r[rt<<1|1];
sum[rt] = max(sum[rt<<1],sum[rt<<1|1]);
}
}

void build(int l,int r,int rt)
{
if (l==r)
{
scanf("%d",&val[l]);
ins_l[rt] = ins_r[rt] = l;
sum[rt] = 1;
return;
}
int m = (l+r)>>1;
build(lson);
build(rson);
PushUp(rt,l,r);
}

void Update(int p,int c,int l,int r,int rt)
{
if (l==r)
{
val[l] = c;
return;
}
int m = (l+r)>>1;
if (p<=m) Update(p,c,lson);
else Update(p,c,rson);
PushUp(rt,l,r);
}

int ans;
pair<int,int> ans1;
void query(int L,int R,int l,int r,int rt)
{
if (L<=l && r<=R)
{
ans = max(ans,sum[rt]);
if (ans1.first < val[l])
{
ans1.first = val[ins_l[rt]];
ans1.second += ins_l[rt]-l+1;
}
else 
{
ans1.first = val[r];
ans1.second = r-ins_r[rt]+1;
}
ans = max(ans,ans1.second);
if (ins_l[rt]!=r) 
{
ans1.second = r-ins_r[rt]+1;
ans1.first = val[r];
}
return;
}
int m = (l+r)>>1;
if (L<=m) query(L,R,lson);
if (R>m) query(L,R,rson);
}


int main()
{
int T;
cin>>T;
while (T--)
{
int n,m;
scanf("%d%d",&n,&m);
build(0,n-1,1);
char oper[10];
int a,b;

while (m--)
{
scanf("%s%d%d",oper,&a,&b);
if (oper[0]=='Q')
{
ans = 0;
ans1.first = inf;
ans1.second = 0;
query(a,b,0,n-1,1);
printf("%d\n",ans);
}
else 
Update(a,b,0,n-1,1);
}
}
}
0 0