zoukankan      html  css  js  c++  java
  • 双端队列xLIS问题

    题目大意

    (N) 个数 (A_i) ,他准备将他们依次插入一个双端队列(每次可以在头或尾插入一个元素),最后将
    整个队列从尾到头看成一个序列,求出最长上升子序列的长度 。他想知道 , (L) 的最大值是多少。

    分析

    很简单,考虑一个数,构造有它的最长上升子序列
    把比他小的放他前面,比他大的放它后面
    比他小的最优的就是以某一个比他小的数为开头的最长下降子序列的长度
    比他大的最优的就是以它为开头的最长上升子序列的长度
    最后相加取最大值即可
    线段树维护 (O(N log N))

    (Code)

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define ls (k << 1)
    #define rs (ls | 1) 
    using namespace std;
    
    const int N = 1e5 + 5;
    int n , a[N] , f[N] , g[N] , V , seg[N * 4] , b[N];
    
    void build(int l , int r , int k)
    {
    	if (l == r)
    	{
    		seg[k] = 0;
    		return;
    	}
    	int mid = (l + r) >> 1;
    	build(l , mid , ls) , build(mid + 1 , r , rs);
    	seg[k] = max(seg[ls] , seg[rs]);
    } 
    
    void update(int l , int r , int k , int x , int v)
    {
    	if (l == r && l == x)
    	{
    		seg[k] = v;
    		return;
    	}
    	int mid = (l + r) >> 1;
    	if (x <= mid) update(l , mid , ls , x , v);
    	else update(mid + 1 , r , rs , x , v);
    	seg[k] = max(seg[ls] , seg[rs]);
    }
    
    int query(int l , int r , int k , int tl , int tr)
    {
    	if (tl > tr) return 0;
    	if (tl <= l && r <= tr) return seg[k];
    	int mid = (l + r) >> 1 , res = 0;
    	if (tl <= mid) res = max(res , query(l , mid , ls , tl , tr));
    	if (tr > mid) res = max(res , query(mid + 1 , r , rs , tl , tr));
    	return res;
    }
    
    int main()
    {
    	freopen("dequexlis.in" , "r" , stdin);
    	freopen("dequexlis.out" , "w" , stdout);
    	scanf("%d" , &n);
    	for(register int i = 1; i <= n; i++) 
    		scanf("%d" , a + i) , b[i] = a[i];
    		
    	sort(b + 1 , b + n + 1);
    	int len = unique(b + 1 , b + n + 1) - b - 1;
    	for(register int i = 1; i <= n; i++) 
    		a[i] = lower_bound(b + 1 , b + len + 1 , a[i]) - b;
    	
    	V = n + 1;
    	build(1 , n , 1);
    	for(register int i = n; i; i--)
    	{
    		f[i] = query(1 , n , 1 , a[i] + 1 , V) + 1;
    		update(1 , n , 1 , a[i] , f[i]);
    	}
    	build(1 , n , 1);
    	for(register int i = n; i; i--)
    	{
    		g[i] = query(1 , n , 1 , 1 , a[i] - 1) + 1;
    		update(1 , n , 1 , a[i] , g[i]);
    	}
    	
    	build(1 , n , 1);
    	for(register int i = 1; i <= n; i++) update(1 , n , 1 , a[i] , g[i]);
    	int ans = 0;
    	for(register int i = 1; i <= n; i++) 
    		ans = max(ans , query(1 , n , 1 , 1 , a[i] - 1) + f[i]);	
    	printf("%d" , ans);
    }
    
  • 相关阅读:
    [转]狼的故事8:生存就是坚持
    [转]狼的故事7:单枪匹马的代价
    如何在GridView的Footer内显示总计?
    javascript中如何正确将日期(Date)字符串转换为日期(Date)对象?
    无限级分类(非递归算法/存储过程版/GUID主键)完整数据库示例_(1)表结构
    [转]狼的故事12:王者的风范
    [转]狼的故事2:光线背后的嚎叫
    vs.net2008正式版发布并提供下载(英文版)
    [转]狼的故事11:以牙还牙
    [转]狼的故事3:百分之百的死亡
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13860866.html
Copyright © 2011-2022 走看看