zoukankan      html  css  js  c++  java
  • HDU-3308 LCIS(区间合并)

    题目大意:给一个整数序列,m次询问,每次询问某个区间中最长连续上升子序列的长度。

    题目分析:线段树区间合并。维护以区间左端开头的、以区间右端点结尾的和区间最长的上升连续序列。

    代码如下:

    # include<bits/stdc++.h>
    using namespace std;
    # define LL long long
    # define mid (l+(r-l)/2)
    
    const int N=100000;
    
    int w[N+5];
    int len[N*4+5];
    int l1[N*4+5],l3[N*4+5];
    int r1[N*4+5],r3[N*4+5];
    
    void pushUp(int rt,int l,int r)
    {
    	len[rt]=0;
    	if(w[mid]<w[mid+1]){
    		if(r1[rt<<1]==mid) r1[rt]=r1[rt<<1|1];
    		else r1[rt]=r1[rt<<1];
    		if(l1[rt<<1|1]==mid+1) l1[rt]=l1[rt<<1];
    		else l1[rt]=l1[rt<<1|1];
    		
    		if(r1[rt<<1|1]-l1[rt<<1]+1>len[rt]){
    			len[rt]=r1[rt<<1|1]-l1[rt<<1]+1;
    			l3[rt]=l1[rt<<1];
    			r3[rt]=r1[rt<<1|1];
    		}
    	}else{
    		l1[rt]=l1[rt<<1|1];
    		r1[rt]=r1[rt<<1];
    	}
    	if(r1[rt]-l+1>len[rt]){
    		len[rt]=r1[rt]-l+1;
    		l3[rt]=l,r3[rt]=r1[rt];
    	}
    	if(r-l1[rt]+1>len[rt]){
    		len[rt]=r-l1[rt]+1;
    		l3[rt]=l1[rt],r3[rt]=r;
    	}
    	if(r3[rt<<1]-l3[rt<<1]+1>len[rt]){
    		len[rt]=r3[rt<<1]-l3[rt<<1]+1;
    		l3[rt]=l3[rt<<1];
    		r3[rt]=r3[rt<<1];
    	}
    	if(r3[rt<<1|1]-l3[rt<<1|1]+1>len[rt]){
    		len[rt]=r3[rt<<1|1]-l3[rt<<1|1]+1;
    		l3[rt]=l3[rt<<1|1];
    		r3[rt]=r3[rt<<1|1];
    	}
    }
    
    void build(int rt,int l,int r)
    {
    	if(l==r){
    		len[rt]=1;
    		l1[rt]=r1[rt]=l;
    		l3[rt]=r3[rt]=l;
    	}else{
    		build(rt<<1,l,mid);
    		build(rt<<1|1,mid+1,r);
    		pushUp(rt,l,r);
    	}
    }
    
    void update(int rt,int l,int r,int p,int x)
    {
    	if(l==r){
    		w[l]=x;
    	}else{
    		if(p<=mid) update(rt<<1,l,mid,p,x);
    		if(p>mid) update(rt<<1|1,mid+1,r,p,x);
    		pushUp(rt,l,r);
    	}
    }
    
    int query(int rt,int l,int r,int L,int R)
    {
    	if(L<=l&&r<=R)
    		return len[rt];
    	if(R<=mid) return query(rt<<1,l,mid,L,R);
    	if(L>mid) return query(rt<<1|1,mid+1,r,L,R);
    	int li=query(rt<<1,l,mid,L,R);
    	int ri=query(rt<<1|1,mid+1,r,L,R);
    	int res=max(li,ri);
    	if(w[mid]<w[mid+1])
    		res=max(res,min(R,r1[rt<<1|1])-max(L,l1[rt<<1])+1);
    	return res;
    }
    
    int main()
    {
    	int T,n,m;
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d%d",&n,&m);
    		for(int i=0;i<n;++i) scanf("%d",w+i);
    		
    		build(1,0,n-1);
    		int a,b;
    		char op[2];
    		while(m--)
    		{
    			scanf("%s%d%d",op,&a,&b);
    			if(op[0]=='Q'){
    				printf("%d
    ",query(1,0,n-1,a,b));
    			}else if(op[0]=='U')
    				update(1,0,n-1,a,b);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    忏悔书(IT攻城狮)
    【博文汇总】彩色图像分割 Menu
    【Android】Android 4.2源码下载(ubuntu 12.10)
    【My Project】织物疵点检测机器视觉系统 软件测试平台
    【NFC】Android NFC API Reference中英文
    【分享】RSS订阅技巧及工具和实用RSS链接分享
    【流媒體】live555—VS2010/VS2013 下live555编译、使用及测试
    vc++ win32项目属性介绍(二、c/c++)
    c风格回调函数 vs c++风格虚基类,关于接口定义和调用的对比
    关于移动技术的我的看法(二)
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5729472.html
Copyright © 2011-2022 走看看