题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308
LCIS
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5792 Accepted Submission(s): 2513
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].
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<=10 5).
The next line has n integers(0<=val<=10 5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10 5)
OR
Q A B(0<=A<=B< n).
Each case starts with two integers n , m(0<n,m<=10 5).
The next line has n integers(0<=val<=10 5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10 5)
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
Author
shǎ崽
Source
Recommend
题目大意:给n个数,m个操作。两种操作:Q a b 表示查询【a,b】这个区间的LCIS(即最长连续递增子序列)的长度。U a b 表示更新第a个数把他变成b(从0开始)。
解题思路:主要解决简单的单点更新和区间的查询,区间记录最长的连续递增子序列长度。要分析清楚各种情况。
详见代码。
#include <iostream>
#include <cstdio>
using namespace std;
struct node
{
int l,r;
int mmax;
int lmax,rmax;
int lnum,rnum;
}s[100000*4+10];
void InitTree(int l,int r,int k)
{
s[k].l=l;
s[k].r=r;
s[k].mmax=1;
s[k].rmax=1;
s[k].lmax=1;
s[k].lnum=s[k].rnum=0;
if (l==r)
return ;
int mid=(l+r)/2;
InitTree(l,mid,2*k);
InitTree(mid+1,r,2*k+1);
}
void UpdataTree(int i,int change,int k)
{
if (s[k].l==s[k].r&&s[k].l==i)
{
s[k].lnum=s[k].rnum=change;
return ;
}
int mid=(s[k].l+s[k].r)/2;
if (i>mid)
UpdataTree(i,change,2*k+1);
else if (i<=mid)
UpdataTree(i,change,2*k);
s[k].lnum=s[k*2].lnum;
s[k].rnum=s[k*2+1].rnum;
s[k].lmax=s[k*2].lmax;
s[k].rmax=s[k*2+1].rmax;
s[k].mmax=max(s[k*2].mmax,s[k*2+1].mmax);
if(s[k*2].rnum<s[k*2+1].lnum)
{
s[k].mmax=max(s[k].mmax,s[k*2].rmax+s[k*2+1].lmax);
if(s[k*2].lmax==s[k*2].r-s[k*2].l+1)
s[k].lmax=s[k*2].lmax+s[k*2+1].lmax;
if(s[k*2+1].rmax==s[k*2+1].r-s[k*2+1].l+1)
s[k].rmax=s[k*2].rmax+s[k*2+1].rmax;
}
}
int SearchTree(int l,int r,int k)
{
if (s[k].l==l&&s[k].r==r)
return s[k].mmax;
else
{
int mid=(s[k].l+s[k].r)/2;
if (l>mid)
return SearchTree(l,r,2*k+1);
else if (r<=mid)
return SearchTree(l,r,2*k);
/*else
{
if (s[k].lnum<s[k].rnum)
return SearchTree(l,mid,2*k)+SearchTree(mid+1,r,2*k+1);
else if
}*/
else
{
int a=min(s[k*2].rmax,mid-l+1);
int b=min(s[k*2+1].lmax,r-mid);
int Max=max(a,b);
Max=max(Max,SearchTree(l,mid,2*k));
Max=max(Max,SearchTree(mid+1,r,2*k+1));
if(s[k*2].rnum<s[2*k+1].lnum)
{
Max=max(Max,a+b);
}
return Max;
}
}
}
int main()
{
int t;
char ch[70];
scanf("%d",&t);
while (t--)
{
int n,m,w,a,b;
scanf("%d%d",&n,&m);
InitTree(0,n-1,1);
for (int i=0; i<n; i++)
{
scanf("%d",&w);
UpdataTree(i,w,1);
}
for (int i=0; i<m; i++)
{
//getchar();
scanf("%s%d%d",ch,&a,&b);
if (ch[0]=='Q')
{
//cout<<"!!!!!!!!!!!!!!!!!"<<endl;
int ans=SearchTree(a,b,1);
printf ("%d\n",ans);
}
else if (ch[0]=='U')
{
UpdataTree(a,b,1);
}
}
}
return 0;
}