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;
    }
    
  • 相关阅读:
    gluoncv faster_rcnn 参数修改
    gluoncv 训练自己的数据集,进行目标检测
    Java面试题及答案2020最新版!
    阿里巴巴Java开发手册泰山版下载
    Java基础之如何取舍Joda与 Java8 日期库
    深入理解Java虚拟机3——垃圾回收
    剖析Java OutOfMemoryError异常
    教你如何理解JAVA的I/O类库
    Java源码解读系列(一):ArrayList
    Java 并发之 Executor 框架
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14622495.html
Copyright © 2011-2022 走看看