题意

给出一个序列的以每一项结尾的 \(LIS\) 的长度a[],求一个序列,使得以每一项为开头的最长下降子序列的长度之和最大。

\(n\leq 10^5\) 。

分析

  • 最优解一定是一个排列,因为如果两个数字的大小相同,完全可以区别他们的大小,以得到更多的贡献。

  • 考虑的 \(a\) 给定的限制,显然对于所有的相同大小的 \(a\) ,前一项 \(a_{p_1}\) 要大于后一项 \(a_{p_2}\),否则一定会产生更长的上升子序列。连边\(p_2\rightarrow p_1\)表示 \(p_2\) 的值小于\(p_1\)。

  • 对于 \(i\),找到上一次出现 \(a[i]-1\) 的位置,并连边 $ {pos}_{a[i]-1}\rightarrow i$ ,表示 \(i\) 要大于此位置的值。

  • 然后进行贪心的操作,每次在所有入度为0的点中选择编号最大的并赋上最小的权值。确定数值之后依次确定 \(b\) 的值就好了。

  • 正确性显然,因为对于相同的 \(a_x\) 来说我们会优先考虑最靠后的 \(last\),同时靠前的不会向 \(last\) 后边连边。

  • 总时间复杂度为 \(O(nlogn)\) ,主要是 \(BIT\) 的复杂度。

代码

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<cctype>
  6. #include<queue>
  7. #include<vector>
  8. using namespace std;
  9. #define fi first
  10. #define se second
  11. #define mp make_pair
  12. #define pb push_back
  13. #define rep(i,a,b) for(int i=a;i<=b;++i)
  14. #define go(u) for(int i=head[u],v=e[i].to;i;i=e[i].last,v=e[i].to)
  15. typedef long long LL;
  16. typedef pair<int,int> pii;
  17. inline int gi(){
  18. int x=0,f=1;char ch=getchar();
  19. while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
  20. while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
  21. return x*f;
  22. }
  23. template<typename T>inline bool Max(T &a,T b){return a<b?a=b,1:0;}
  24. template<typename T>inline bool Min(T &a,T b){return a>b?a=b,1:0;}
  25. const int N=1e5 + 7;
  26. int n,edc;
  27. int head[N],ind[N],lst[N],a[N],b[N],f[N];
  28. struct edge{
  29. int last,to;
  30. edge(){}edge(int last,int to):last(last),to(to){}
  31. }e[N*2];
  32. void Add(int a,int b){
  33. e[++edc]=edge(head[a],b),head[a]=edc;
  34. ++ind[b];
  35. }
  36. int tr[N];
  37. int lowbit(int x){return x&-x;}
  38. void modify(int x,int y){for(int i=x;i<=n;i+=lowbit(i)) Max(tr[i],y);}
  39. int query(int x){int res=0;for(int i=x;i;i-=lowbit(i)) Max(res,tr[i]);return res;}
  40. priority_queue<int>Q;
  41. void topo(){
  42. rep(i,1,n) if(!ind[i]) Q.push(i);int tmp=0;
  43. while(!Q.empty()){
  44. int u=Q.top();Q.pop();
  45. b[u]=++tmp;
  46. go(u)
  47. if(--ind[v]==0) Q.push(v);
  48. }
  49. }
  50. int main(){
  51. n=gi();
  52. rep(i,1,n){
  53. a[i]=gi();
  54. if(lst[a[i]]) Add(i,lst[a[i]]);
  55. if(lst[a[i]-1]) Add(lst[a[i]-1],i);
  56. lst[a[i]]=i;
  57. }
  58. topo();
  59. LL ans=0;
  60. for(int i=n;i;--i){
  61. f[i]=query(b[i]-1)+1;
  62. modify(b[i],f[i]);
  63. ans+=f[i];
  64. }
  65. printf("%lld\n",ans);
  66. return 0;
  67. }

[TJOI2014]Alice and Bob[拓扑排序+贪心]的更多相关文章

  1. BZOJ_4010_[HNOI2015]菜肴制作_拓扑排序+贪心

    BZOJ_4010_[HNOI2015]菜肴制作_拓扑排序+贪心 Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜 ...

  2. 2019.01.20 bzoj5158 Alice&Bob(拓扑排序+贪心)

    传送门 短代码简单题. 题意简述:对于一个序列XXX,定义其两个伴随序列a,ba,ba,b,aia_iai​表示以第iii个数结尾的最长上升子序列长度,bib_ibi​表示以第iii个数开头的最长下降 ...

  3. BZOJ5158 [Tjoi2014]Alice and Bob 【贪心 + 拓扑】

    题目链接 BZOJ5158 题解 题中所给的最长上升子序列其实就是一个限制条件 我们要构造出最大的以\(i\)开头的最长下降子序列,就需要编号大的点的权值尽量小 相同时当然就没有贡献,所以我们不妨令权 ...

  4. POJ3687 Labeling Balls(拓扑排序\贪心+Floyd)

    题目是要给n个重量1到n的球编号,有一些约束条件:编号A的球重量要小于编号B的重量,最后就是要输出字典序最小的从1到n各个编号的球的重量. 正向拓扑排序,取最小编号给最小编号是不行的,不举出个例子真的 ...

  5. HDU 4857 逃生(反向建边的拓扑排序+贪心思想)

    逃生 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...

  6. BZOJ2535: [Noi2010]Plane 航空管制2(拓扑排序 贪心)

    题意 题目链接 Sol 非常妙的一道题. 首先不难想到拓扑排序,但是直接对原图按\(k\)从小到大拓扑排序是错的.因为当前的\(k\)大并不意味着后面的点\(k\)也大 但是在反图上按\(k\)从大到 ...

  7. [TJOI2014] Alice and Bob

    非常好的一道思维性题目,想了很久才想出来qwq(我好笨啊) 考虑a[]数组有什么用,首先可以yy出一些性质 (设num[i]为原来第i个位置的数是什么 , 因为题目说至少有一个排列可以满足a[],所以 ...

  8. [LOJ2114][HNOI2015]-菜肴制作-拓扑排序+贪心

    <题面> 一个蒟蒻的痛苦一天 在今天的节目集训中,麦蒙将带领大家学习9种错误的解题策略 $15\%$算法(看两个就往下走吧) 1> puts("Impossible!&qu ...

  9. POJ3687拓扑排序+贪心

    题意:       给你n个求,他们的重量是1-n(并不是说1号求的重量是1...),然后给你m组关系a,b,表示a的重量小于b的重量,然后让你输出满足要求的前提下每个球的重量,要求字典序最小. 思路 ...

随机推荐

  1. [翻译] DoImagePickerController

    DoImagePickerController An image picker controller with single selection and multiple selection. Sup ...

  2. Linux 系统的主机别名文件

    修改主机名文件 # 方式一: 临时生效 hostname 主机名 hostname omc 临时生效 # 方式二: 编辑配置文件[永久生效] vim /etc/sysconfig/network [更 ...

  3. 最大公约数(GCD)与最小公倍数(LCM)的计算

    给出两个数a.b,求最大公约数(GCD)与最小公倍数(LCM) 一.最大公约数(GCD)    最大公约数的递归:  * 1.若a可以整除b,则最大公约数是b  * 2.如果1不成立,最大公约数便是b ...

  4. wrap装饰器包

    import wrapt # without argument in decorator @wrapt.decorator def logging(wrapped, instance, args, k ...

  5. EclEmma安装与使用

    安装 EclEmma 插件的过程和大部分 Eclipse 插件相同,我们既可以通过 Eclipse 标准的 Update 机制来远程安装 EclEmma 插件(图 1),也可以从站点(参阅参考资源)下 ...

  6. Oracle中修改sysman和dbsnmp密码正确流程

    1.停止dbconsole $ emctl stop dbconsole 查看状态,确认dbconsole已经停止 $ emctl status dbconsole   2.修改sysman用户和db ...

  7. window7远程桌面到server不能复制粘贴解决的方法

    用远程桌面登陆server不能在本机和远程server之间粘贴文本了,即不能从本机复制文本粘贴到server,也不能从server复制文本粘贴到本机. 下面是解决方法之中的一个,试了几次都非常管用户: ...

  8. log4j配置不生效

    可能原因是打包时候log4j.properties没有在classpath下面或者是加载时候被其他第三方jar包中的log4j.properties文件覆盖掉了,可以使用如下命令进行查看log4j具体 ...

  9. Hadoop学习之路(七)Hadoop集群shell常用命令

    Hadoop常用命令 启动HDFS集群 [hadoop@hadoop1 ~]$ start-dfs.sh Starting namenodes on [hadoop1] hadoop1: starti ...

  10. 关于HTML Button点击自动刷新页面的问题解决

    原因 button,input type=button按钮在IE和w3c,firefox浏览器区别: 1.当在IE浏览器下面时,button标签按钮,input标签type属性为button的按钮是一 ...