zoukankan      html  css  js  c++  java
  • hdu3308 LCIS

    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

    这题属于线段树区间合并,题意是求一个区间内的最长连续递增子序列。首先用线段树维护7个节点,l,r,llen,rlen,tlen,lnum,rnum;(llen,rlen表示这段区间从最左(右)向右(左)可以持续的最大递增子序列长度。tlen表示这条线段的最大递增子序列长度,lnum,rnum表示这段线段最左边和左右边的值)。我在一开始建树的时候就把7个初始化好了,这样下面就比较方便。

    这里的难点是查询,当查询区间全落在左子树或者右子树的时候比较简单,直接算子树的最大长度,但落在中间的时候要考虑合并的值,这里合并时注意不能直接用b[i*2].rlen+b[i*2+1].llen,因为查询的区间(l,r)可能大于b[2*i+1].l+b[2*i+1].llen-1或者小于b[2*i].r-b[2*i].rlen+1,这样就要分类讨论。这里卡了很长时间= =。

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<queue>
    #include<stack>
    #include<string>
    #include<algorithm>
    using namespace std;
    int a[100005],num;
    char s[10];
    struct node{
    	int l,r,llen,rlen,tlen,lnum,rnum;
    }b[8*100005];
    int max(int a,int b){
    	return a>b?a:b;
    }
    
    void build(int l,int r,int i)
    {
    	int mid;
    	b[i].l=l;b[i].r=r;
    	if(l==r){
    		b[i].lnum=b[i].rnum=a[l];
    		b[i].rlen=b[i].llen=b[i].tlen=1;
    		return;
    	}
    	mid=(l+r)/2;
    	build(l,mid,i*2);
    	build(mid+1,r,i*2+1);
    	b[i].lnum=b[i*2].lnum;
    	b[i].rnum=b[i*2+1].rnum;
    	b[i].tlen=max(b[i*2].tlen,b[i*2+1].tlen);
    	if(b[i*2].rnum<b[i*2+1].lnum){
    		b[i].tlen=max(b[i].tlen,b[i*2].rlen+b[i*2+1].llen);
    	}
    	b[i].llen=b[i*2].llen;
    	if(b[i*2].rnum<b[i*2+1].lnum && b[i*2].llen==(b[i*2].r-b[i*2].l+1)){
    		b[i].llen+=b[i*2+1].llen;
    	}
    	b[i].rlen=b[i*2+1].rlen;
    	if(b[i*2].rnum<b[i*2+1].lnum && b[i*2+1].rlen==(b[i*2+1].r-b[i*2+1].l+1)){
    		b[i].rlen+=b[i*2].rlen;
    	}
    }
    
    void update(int index,int num,int i)
    {
    	int mid;
    	if(b[i].l==b[i].r){
    		b[i].rnum=b[i].lnum=num;return;
    	}
    	if(b[i*2].r-b[i*2].l+1>=index)update(index,num,i*2);
    	else update(index-(b[i*2].r-b[i*2].l+1),num,i*2+1);
    	b[i].lnum=b[i*2].lnum;
    	b[i].rnum=b[i*2+1].rnum;
    	b[i].tlen=max(b[i*2].tlen,b[i*2+1].tlen);
    	if(b[i*2].rnum<b[i*2+1].lnum){
    		b[i].tlen=max(b[i].tlen,b[i*2].rlen+b[i*2+1].llen);
    	}
    	b[i].llen=b[i*2].llen;
    	if(b[i*2].rnum<b[i*2+1].lnum && b[i*2].llen==(b[i*2].r-b[i*2].l+1)){
    		b[i].llen+=b[i*2+1].llen;
    	}
    	b[i].rlen=b[i*2+1].rlen;
    	if(b[i*2].rnum<b[i*2+1].lnum && b[i*2+1].rlen==(b[i*2+1].r-b[i*2+1].l+1)){
    		b[i].rlen+=b[i*2].rlen;
    	}
    }
    
    void question(int l,int r,int i)
    {
    	int mid,r1,l1;
    	if(b[i].l==l && b[i].r==r){
    		num=max(num,b[i].tlen);return;
    	}
    	mid=(b[i].l+b[i].r)/2;
    	if(r<=mid)question(l,r,i*2);
    	else if(l>mid)question(l,r,i*2+1);
    	else if(l<=mid && r>mid){
    		if(b[i*2].rnum<b[i*2+1].lnum){
    			if(b[2*i+1].l+b[2*i+1].llen-1>=r)r1=r;
    			else r1=b[2*i+1].l+b[2*i+1].llen-1;
    			if(b[2*i].r-b[2*i].rlen+1<=l)l1=l;
    			else l1=b[2*i].r-b[2*i].rlen+1;
    			num=max(num,r1-l1+1);
    		}
    		question(l,mid,i*2);
    		question(mid+1,r,i*2+1);
    	}
    }
    
    int main()
    {
    	int n,m,i,j,T,c,d;
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d%d",&n,&m);
    		for(i=1;i<=n;i++){
    			scanf("%d",&a[i]);
    		}
    		build(1,n,1);
    		for(i=1;i<=m;i++){
    			scanf("%s",s);
    			if(s[0]=='Q'){
    				scanf("%d%d",&c,&d);
    				num=0;
    				question(c+1,d+1,1);
    				printf("%d
    ",num);
    			}
    			else if(s[0]=='U'){
    				scanf("%d%d",&c,&d);
    				update(c+1,d,1);
    			}
    		}
    	}
    	return 0;
    }


  • 相关阅读:
    51nod 1574 排列转换(猜结论)
    百度之星资格赛 1005 寻找母串(分块打表+组合数计算)
    百度之星资格赛 1004 度度熊的午饭时光(01背包+最小序号和+字典序+有bug)
    百度之星资格赛 1003 度度熊与邪恶大魔王(二维dp)
    HDU 4542 小明系列故事——未知剩余系 (数论|反素数)
    51nod 1060 最复杂的数(反素数)
    eclipse hadoop环境搭建 查看HDFS文件内容
    Windows jdk安装以及版本切换
    WIN10配置MongoDB
    Oracle 11g R2 for Win10(64位)的安装步骤
  • 原文地址:https://www.cnblogs.com/herumw/p/9464788.html
Copyright © 2011-2022 走看看