题目描述

«问题描述:

给定正整数序列x1,...,xn 。

(1)计算其最长不下降子序列的长度s。

(2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列。

(3)如果允许在取出的序列中多次使用x1和xn,则从给定序列中最多可取出多少个长度为s的不下降子序列。

«编程任务:

设计有效算法完成(1)(2)(3)提出的计算任务。

输入输出格式

输入格式:

第1 行有1个正整数n,表示给定序列的长度。接下来的1 行有n个正整数n:x1, ..., xn。

输出格式:

第1 行是最长不下降子序列的长度s。第2行是可取出的长度为s 的不下降子序列个数。第3行是允许在取出的序列中多次使用x1和xn时可取出的长度为s 的不下降子序列个数。

输入输出样例

输入样例#1:

4
3 6 2 5
输出样例#1:

2
2
3

说明

n≤500

Solution:

  本题简单dp+最大流。

  第一问直接煞笔dp。

  第二问求最多取出多少个长度为$x=max(f[i])$的子序列,因为每个数要么不选要么只选1次,这样有上下界的题目,考虑拆点跑最大流咯,将每个数拆成$i\rightarrow i'$连流量为1,若$f[i]==1$则$s\rightarrow i$连流量为1,若$f[i]==x$则$i'\rightarrow t$连流量为1,若$f[i]==f[j]+1,j<i,a_j\leq a_i$则$j'\rightarrow i$连流量为1,跑最大流就好了。

  第三问可以重复用$a_1$和$a_n$,那么改变的就是与这两点直接相关的边的流量了,我们在第二问的答案基础上,加入新边,$1\rightarrow 1'$流量inf,$n\rightarrow n'$流量inf,$s\rightarrow 1$流量inf,若$f[n]==x$则$n'\rightarrow t$流量inf,再跑下最大流就好了。

  (实际上本题第三问有bug,比如最长不下降子序列长度为1,那么第三问答案就应该是inf了,inf不确定,于是乎出锅咯!反正实践证明没这数据,嘿嘿嘿!>.@_@.<)

代码:

/*Code by 520 -- 9.1*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
using namespace std;
const int N=,M=,inf=0x7fffffff;
int n,a[N],f[N],s,t=;
int h[N],dis[N],to[M],net[M],w[M],cnt=;
int ans1,ans2; il void add(int u,int v,int c){
to[++cnt]=v,net[cnt]=h[u],w[cnt]=c,h[u]=cnt;
to[++cnt]=u,net[cnt]=h[v],w[cnt]=,h[v]=cnt;
} il bool bfs(){
queue<int>q;
memset(dis,-,sizeof(dis));
q.push(s),dis[s]=;
while(!q.empty()){
RE int u=q.front();q.pop();
for(RE int i=h[u];i;i=net[i])
if(dis[to[i]]==-&&w[i]) dis[to[i]]=dis[u]+,q.push(to[i]);
}
return dis[t+]!=-;
} int dfs(int u,int op){
if(u==t+)return op;
int flow=,used=;
for(RE int i=h[u];i;i=net[i]){
int v=to[i];
if(dis[v]==dis[u]+&&w[i]){
used=dfs(v,min(op,w[i]));
if(!used)continue;
flow+=used,op-=used;
w[i]-=used,w[i^]+=used;
if(!op)break;
}
}
if(!flow) dis[u]=-;
return flow;
} il void init(){
scanf("%d",&n);
For(i,,n) scanf("%d",&a[i]),f[i]=;
For(i,,n) For(j,,i-) if(a[i]>=a[j]) f[i]=max(f[i],f[j]+);
For(i,,n) ans1=max(ans1,f[i]);
printf("%d\n",ans1);
For(i,,n) {
add(i,i+n,);
if(f[i]==) add(i+n,t,);
if(f[i]==ans1) add(s,i,);
}
add(t,t+,inf);
For(i,,n) For(j,,i-) if(f[i]==f[j]+&&a[i]>=a[j]) add(i+n,j,);
while(bfs()) ans2+=dfs(s,inf);
printf("%d\n",ans2);
add(n+,t,inf),add(,n+,inf),add(n,n<<,inf);
if(f[n]==ans1) add(s,n,inf);
while(bfs()) ans2+=dfs(s,inf);
printf("%d\n",ans2);
} int main(){
init();
return ;
}

P2766 最长不下降子序列问题的更多相关文章

  1. 【24题】P2766最长不下降子序列问题

    网络流二十四题 网络流是个好东西,希望我也会. 网络流?\(orz\ zsy!!!!!\) P2766 最长不下降子序列问题 考虑我们是如何\(dp\)这个\(LIS\)的. 我们是倒着推,设置\(d ...

  2. [**P2766** 最长不下降子序列问题](https://www.luogu.org/problemnew/show/P2766)

    P2766 最长不下降子序列问题 考虑我们是如何\(dp\)这个\(LIS\)的. 我们是倒着推,设置\(dp(i)\)代表以\(i\)为起点的\(LIS\)是多少.转移太显然了 \[ dp(i)=m ...

  3. P2766 最长不下降子序列问题 网络流重温

    P2766 最长不下降子序列问题 这个题目还是比较简单的,第一问就是LIS 第二问和第三问都是网络流. 第二问要怎么用网络流写呢,首先,每一个只能用一次,所以要拆点. 其次,我们求的是长度为s的不下降 ...

  4. P2766 最长不下降子序列问题 网络流

    link:https://www.luogu.org/problemnew/show/P2766 题意 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的 ...

  5. 网络流 之 P2766 最长不下降子序列问题

    题目描述 «问题描述: 给定正整数序列x1,...,xn . (1)计算其最长不下降子序列的长度s. (2)计算从给定的序列中最多可取出多少个长度为s的不下降子序列. (3)如果允许在取出的序列中多次 ...

  6. 【题解】Luogu P2766 最长不下降子序列问题

    原题传送门 实际还是比较套路的建图 先暴力dp一下反正数据很小 第一小问的答案即珂以求出数列的最长不下降子序列的长度s 考虑第二问如何做: 将每个点拆点 从前向后连一条流量为1的边 如果以它为终点的最 ...

  7. 洛谷P2766 最长不下降子序列问题(最大流)

    传送门 第一问直接$dp$解决,求出$len$ 然后用$f[i]$表示以$i$为结尾的最长不下降子序列长度,把每一个点拆成$A_i,B_i$两个点,然后从$A_i$向$B_i$连容量为$1$的边 然后 ...

  8. 【Luogu】P2766最长不下降子序列问题(暴力网络流)

    题目链接 水题qwq,数据都那么水. 我要是出数据的人我就卡$n^3$建图. qwq. 然而这么水的题我!居!然!没!有!1!A!!还!提!交!了!五!遍!!! md从现在开始要锻炼1A率了 看我从今 ...

  9. 洛谷 P2766 最长不下降子序列问【dp+最大流】

    死于开小数组的WA?! 第一问n方dp瞎搞一下就成,f[i]记录以i结尾的最长不下降子序列.记答案为mx 第二问网络流,拆点限制流量,s向所有f[i]为1的点建(s,i,1),所有f[i]为mx(i+ ...

随机推荐

  1. (ex)Lucas总结

    (ex)Lucas总结 普通Lucas 求 \[ C_n^m\;mod\;p \] 其中\(n,m,p\leq 10^5\)其中\(p\)为质数 公式不难背,那就直接背吧... \[ C_n^m\;m ...

  2. SPOJ 694&&SPOJ705: Distinct Substrings

    DISUBSTR - Distinct Substrings 链接 题意: 询问有多少不同的子串. 思路: 后缀数组或者SAM. 首先求出后缀数组,然后从对于一个后缀,它有n-sa[i]-1个前缀,其 ...

  3. 【JUC源码解析】CountDownLatch

    简介 CountDownLatch,是一个同步器,允许一个或多个线程等待,直到一组操作在其他线程中完成. 概述 初始CountDownLatch时,会给定count,await方法会阻塞,直到coun ...

  4. 【MYSQL用户创建报错】ERROR 1396 (HY000): Operation CREATE USER failed for 'user1'@'%'

    原文参考自:http://blog.csdn.net/u011575570/article/details/51438841 1.创建用户的时候报错ERROR 1396 (HY000): Operat ...

  5. SQL Server 2008 R2 链接 Oracle 10g

    首先sqlserver 链接oracle可以通过两个访问接口: “MSDAORA” 和“OraOLEDB.Oracle” 1.“MSDAORA”访问接口是由Microsoft OLE DB Provi ...

  6. 「Leetcode」974. Subarray Sums Divisible by K(Java)

    分析 这题场上前缀和都想出来了,然后就没有然后了...哭惹.jpg 前缀和相减能够得到任意一段连续区间的和,然后他们取余\(K\)看余数是否为0就能得到.这是朴素的遍历算法.那么反过来说,如果两个前缀 ...

  7. K8S-RedisCluster搭建

    简介         Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接, mastart节点之间存放的数据并不是相同的,只是其中的一部分,当我们请 ...

  8. ntp时钟服务器配置

    集群中时间不同步有可能会让大数据的应用程序运行混乱,造成不可预知的问题,比如Hbase,当时间差别过大时就会挂掉,所以在大数据集群中,ntp服务,应该作为一种基础的服务,以下在演示在CentOS 7. ...

  9. java面向对象的有序数组和无序数组的比较

    package aa; class Array{ //定义一个有序数组 private long[] a; //定义数组长度 private int nElems; //构造函数初始化 public ...

  10. Scrum立会报告+燃尽图(十一月十五日总第二十三次):代码规范与技术交流

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2384 项目地址:https://git.coding.net/zhang ...