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);
    }
    
  • 相关阅读:
    面向对象的继承关系体现在数据结构上时,如何表示
    codeforces 584C Marina and Vasya
    codeforces 602A Two Bases
    LA 4329 PingPong
    codeforces 584B Kolya and Tanya
    codeforces 584A Olesya and Rodion
    codeforces 583B Robot's Task
    codeforces 583A Asphalting Roads
    codeforces 581C Developing Skills
    codeforces 581A Vasya the Hipster
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13860866.html
Copyright © 2011-2022 走看看