HDU3308--LCIS(线段树)

版权声明: https://blog.csdn.net/qq_40791842/article/details/82527962

题目链接: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): 9048    Accepted Submission(s): 3922


 

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<=_{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

题意:n个数,m个操作,操作包括单点修改和区间查询最长递增子序列,对每个查询输出答案。

解法:使线段树上的每个区间维护从头开始的最长连续递增子序列的长度(lmax),从尾开始的倒序最长连续递减子序列的长度(rmax),以及区间最长递增子序列长度;

代码:

#include<iostream>
#include<cstdio>
#include<vector>
#include<bitset>
#include<stack>
#include<set>
#include<queue>
#include<map>
#include<cmath>
#include<string>
#include<cstring>
#include<ctime>
#include<fstream>
#include<cstdlib>
#include<algorithm>

using namespace std;

#define pii pair<int, int>
#define mp(a,b) make_pair(a,b)
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define per(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a,b) for(int i=a;i>=b;i--)
#define PI 3.1415926535897932384626433832795
#define inf 0x3f3f3f3f
typedef long long ll;
const double eps=1.0e-5;
const int maxn=100000+10;

int t,n,m,a,b,ans,tmp,len;
char choice[10];

struct node{
	int l,r;
	int lx,rx; //lx是左端点值,rx是右端点值
	int lmax,rmax,mmax;
}tree[maxn<<2];

void go_up(int k)
{
	tree[k].lx=tree[k<<1].lx;tree[k].rx=tree[k<<1|1].rx;
	if(tree[k<<1].lmax==tree[k<<1].r-tree[k<<1].l+1){
		if(tree[k<<1].rx<tree[k<<1|1].lx){
			tree[k].lmax=tree[k<<1].lmax+tree[k<<1|1].lmax;
		}else{
			tree[k].lmax=tree[k<<1].lmax;
		}
	}else{
		tree[k].lmax=tree[k<<1].lmax;
	}
	
	if(tree[k<<1|1].rmax==tree[k<<1|1].r-tree[k<<1|1].l+1){
		if(tree[k<<1|1].lx>tree[k<<1].rx){
			tree[k].rmax=tree[k<<1].rmax+tree[k<<1|1].rmax;
		}else{
			tree[k].rmax=tree[k<<1|1].rmax;
		}
	}else{
		tree[k].rmax=tree[k<<1|1].rmax;
	}
	
	tree[k].mmax=max(tree[k].lmax,max(tree[k].rmax,max(tree[k<<1].mmax,tree[k<<1|1].mmax)));
	if(tree[k<<1].rx<tree[k<<1|1].lx) tree[k].mmax=max(tree[k].mmax,tree[k<<1].rmax+tree[k<<1|1].lmax);
}

void build(int le,int ri,int k)
{
	tree[k].l=le,tree[k].r=ri;
	if(le==ri){
		scanf("%d",&tree[k].lx);
		tree[k].rx=tree[k].lx;
		tree[k].lmax=tree[k].rmax=tree[k].mmax=1;
		return;
	}
	int mid=(le+ri)>>1;
	build(le,mid,k<<1);
	build(mid+1,ri,k<<1|1);
	go_up(k);
}

void update(int k)
{
	if(tree[k].l==tree[k].r){
		tree[k].lmax=tree[k].rmax=tree[k].mmax=1;
		tree[k].lx=tree[k].rx=b;
		return;
	}
	
	int mid=(tree[k].l+tree[k].r)>>1;
	if(a<=mid) update(k<<1);
	else update(k<<1|1);
	
	go_up(k);
}

void query(int k)
{
	if(a<=tree[k].l&&tree[k].r<=b){
		if(tree[k].lx>tmp){
			if(tree[k].lmax==tree[k].r-tree[k].l+1){
				len+=tree[k].lmax;
			    tmp=tree[k].rx;
			    ans=max(ans,len);
			}
			else{
				len+=tree[k].lmax;
				ans=max(ans,len);
				len=tree[k].rmax;
			    tmp=tree[k].rx;
			}
		}else{
			len=tree[k].rmax;
			tmp=tree[k].rx;
			ans=max(ans,len);
		}
		ans=max(ans,max(tree[k].lmax,max(tree[k].rmax,tree[k].mmax)));
		return;
	}
	
	int mid=(tree[k].l+tree[k].r)>>1;
	if(a<=mid) query(k<<1);
	if(b>mid) query(k<<1|1);
}

int main()
{
	//freopen("C:\\Users\\MAC\\Desktop\\in.txt","r",stdin);
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		build(1,n,1);
		per(i,1,m){
			scanf("%s %d %d",choice,&a,&b);
			if(choice[0]=='Q'){
				a++;b++;
				ans=0;
				tmp=inf;
				query(1);
				printf("%d\n",ans);
			}else{
				a++;
				update(1);
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40791842/article/details/82527962