zoukankan      html  css  js  c++  java
  • P3971[TJOI2014]Alice and Bob【贪心】

    正题

    题目链接:https://www.luogu.com.cn/problem/P3971


    题目大意

    一个\(1\sim n\)的一个排列,设\(a_i\)表示以\(i\)结尾的最长上升子序列长度,\(b_i\)表示以\(i\)开头的最长下降子序列长度。

    给出序列\(a\)求序列\(b\)的最大和。

    \(1\leq n\leq 10^5\)


    解题思路

    考虑数组\(a\)带来的限制

    • 对于一个\(a_i=a_j=w(i<j)\)那么有\(x_i>x_j\)
    • 对于一个\(a_j=w+1\)前一个最近的\(a_i=w\)那么有\(x_i<x_j\)

    第一个限制其实不用管,因为如果我们要最优,一定会满足那个限制。

    考虑第二个限制,我们将\(i\)\(j\)连一条边,这样我们就可以得到一棵树(把\(0\)视为虚根的话)。

    那么我们子节点的权值一定要比父节点的大,然后在满足这个的前提下我们优先扩展编号大的节点就好了。

    也就是从大到小跑一遍\(dfs\)序就可以得到\(x\)数组。

    然后用树状数组统计一下答案。

    时间复杂度\(O(n\log n)\)


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define lowbit(x) (x&-x)
    using namespace std;
    const int N=1e5+10;
    struct node{
    	int to,next;
    }a[N];
    int n,tot,cnt,dfn[N],ls[N],t[N],las[N];
    long long ans;
    void addl(int x,int y){
    	a[++tot].to=y;
    	a[tot].next=ls[x];
    	ls[x]=tot;return;
    }
    void dfs(int x){
    	dfn[x]=++cnt;
    	for(int i=ls[x];i;i=a[i].next)
    		dfs(a[i].to);
    	return;
    }
    void Change(int x,int val){
    	while(x<=n){
    		t[x]=max(t[x],val);
    		x+=lowbit(x);
    	}
    	return;
    }
    int Ask(int x){
    	int ans=0;
    	while(x){
    		ans=max(ans,t[x]);
    		x-=lowbit(x);
    	}
    	return ans;
    }
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		int x;scanf("%d",&x);
    		addl(las[x-1],i);las[x]=i; 
    	}
    	cnt=-1;dfs(0);
    	for(int i=n;i>=1;i--){
    		int t=Ask(dfn[i])+1;
     		ans+=t;
    		Change(dfn[i],t);
    	}
    	printf("%lld\n",ans);
    	return 0;
    }
    
  • 相关阅读:
    11111 Generalized Matrioshkas
    Uva 442 Matrix Chain Multiplication
    Uva 10815 Andy's First Dictionary
    Uva 537 Artificial Intelligence?
    Uva 340 MasterMind Hints
    SCAU 9508 诸葛给我牌(水泥题)
    Uva 10420 List of Conquests(排序水题)
    Uva 409 Excuses, Excuses!
    10/26
    11/2
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14622495.html
Copyright © 2011-2022 走看看