博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[bzoj5158][Tjoi2014]Alice and Bob
阅读量:5135 次
发布时间:2019-06-13

本文共 1222 字,大约阅读时间需要 4 分钟。

好羞愧啊最近一直在刷水。。。

题意:给定序列$c$的$a_i$,构造出一个序列$c$使得$\sum b_i$最大。

其中$a_i$表示以$c_i$结尾的最长上升子序列长度,$b_i$表示以$c_i$为开头的最长下降子序列长度。

首先$a_i = x$一定是从一个$a_j = x-1$转移而来的。这里让$a_i$从所有$a_j = x-1$的$a_j$里$c_j$最小的转移而来,一定不会有更优的转移。

因为这样它还可以和其它$a_j$做出至少1的贡献。那么我们由$i$向$j$连边。这样会形成一棵以0为根的树,后连边的点先遍历,令$c_j $等于dfs序。这样得到的序列就可以满足题意。求一遍$b$就行了。

#include
using namespace std;const int N=100010;inline int read(){ int r=0,c=getchar(); while(!isdigit(c))c=getchar(); while(isdigit(c)) r=r*10+c-'0',c=getchar(); return r;}struct Edge{ int to,nxt;}e[N*2];int head[N],cnt=1;void add(int u,int v){ e[cnt]=(Edge){v,head[u]}; head[u]=cnt++;}int a[N],las[N],n,dc;void dfs(int u){ a[u]=++dc; for(int i=head[u];i;i=e[i].nxt) dfs(e[i].to);}int b[N],c[N];void upd(int x,int v){ for(int i=x;i<=n;i+=i&-i) c[i]=max(c[i],v);}int ask(int x){ int ret=0; for(int i=x;i;i-=i&-i) ret=max(ret,c[i]); return ret;}int main(){ n=read(); for(int i=1;i<=n;i++){ int x=read(); add(las[x-1],i); las[x]=i; } dfs(0); long long ans=0; for(int i=n;i;i--){ b[i]=ask(a[i]-1)+1; ans+=1ll*b[i]; upd(a[i],b[i]); } cout<

 

转载于:https://www.cnblogs.com/orzzz/p/8444149.html

你可能感兴趣的文章
练习 后缀数组
查看>>
洛谷P3676 小清新数据结构题(动态点分治)
查看>>
[C++] 前置++与后置++
查看>>
c#制作飘动动画窗体
查看>>
正则表达式中/i,/g,/ig,/gi,/m的区别和含义
查看>>
disable jboss JMXInvokerServlet .
查看>>
JavaScript事件冒泡简介及应用
查看>>
Oracle学习 实战心得总结
查看>>
Oracle学习 第20天 PL/SQL导入
查看>>
[USACO10MAR]伟大的奶牛聚集
查看>>
Android跳转到拨打电话的页面
查看>>
【codeforces】【比赛题解】#950 CF Round #469 (Div. 2)
查看>>
Linux字符模式下如何设置/删除环境变量
查看>>
HTTPS加密原理(转)
查看>>
开发动态编辑的表格
查看>>
iPad pro & 显示器
查看>>
吴恩达深度学习笔记(十一)—— dropout正则化
查看>>
lisp 编程入门
查看>>
webgl与opengl技术资讯
查看>>
python基础知识一
查看>>