原题传送门

实际还是比较套路的建图

先暴力dp一下反正数据很小

第一小问的答案即珂以求出数列的最长不下降子序列的长度s

考虑第二问如何做:

将每个点拆点

从前向后连一条流量为1的边

如果以它为终点的最长不下降子序列长度为1,从源点向它(前)连一条流量为1的边

如果以它为终点的最长不下降子序列长度为s,从它(后)向汇点连一条流量为1的边

如果一个点为终点的最长不下降子序列长度加一等于以它后面一个点为终点最长不下降子序列长度且(注意:是而且)前者的数值小于等于后者的数值,珂以从前者(后)向后者(前)连一条流量为1的边

跑一下ISAP就的出子任务2的答案

第三个子问题很简单,只需再稍加改进

从源点向1号点(前)连一条流量为inf的边,从1号点前面向后连一条流量为inf的边

当以n号点为终点的最长不下降子序列长度为s,从n号点(后)向汇点连一条流量为inf的边,从n号点前面向后连一条流量为inf的边

在跑一边ISAP就能求出子问题3的答案

注意:子任务3最大流算出来的答案要加上子任务2的答案(做子任务3时ISAP跑的图已经是残量网络了)

#include <bits/stdc++.h>
#define N 505
#define M 50005
#define inf 0x7f7f7f7f
#define getchar nc
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline int Max(register int a,register int b)
{
return a>b?a:b;
}
inline int Min(register int a,register int b)
{
return a<b?a:b;
}
struct node{
int to,nxt,v;
}e[M];
int head[N<<1],cnt=1;
inline void add(register int u,register int v,register int val)
{
e[++cnt]=(node){v,head[u],val};
head[u]=cnt;
}
int n,a[N],f[N],len=0,s,t,nn;
int dep[N<<1],gap[N<<1],cur[N<<1],maxflow;
inline void bfs()
{
memset(dep,-1,sizeof(dep));
memset(gap,0,sizeof(gap));
dep[t]=0;
++gap[dep[t]];
queue<int> q;
q.push(t);
while(!q.empty())
{
int u=q.front();
q.pop();
for(register int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(dep[v]!=-1)
continue;
q.push(v);
dep[v]=dep[u]+1;
++gap[dep[v]];
}
}
}
inline int dfs(register int u,register int flow)
{
if(u==t)
{
maxflow+=flow;
return flow;
}
int used=0;
for(register int i=cur[u];i;i=e[i].nxt)
{
cur[u]=i;
int v=e[i].to;
if(e[i].v&&dep[v]+1==dep[u])
{
int tmp=dfs(v,Min(e[i].v,flow-used));
if(tmp)
{
e[i].v-=tmp;
e[i^1].v+=tmp;
used+=tmp;
}
if(used==flow)
return used;
}
}
--gap[dep[u]++]==0?dep[s]=nn+1:++gap[dep[u]];
return used;
}
inline void ISAP()
{
bfs();
while(dep[s]<nn)
{
memcpy(cur,head,sizeof(head));
dfs(s,inf);
}
}
int main()
{
n=read();
for(register int i=1;i<=n;++i)
{
a[i]=read(),f[i]=1;
for(register int j=1;j<i;++j)
if(a[j]<=a[i])
f[i]=Max(f[i],f[j]+1);
len=Max(len,f[i]);
}
write(len),puts("");
s=0,t=(n<<1)+1;
for(register int i=1;i<=n;++i)
{
add(i,i+n,1),add(i+n,i,0);
if(f[i]==1)
add(s,i,1),add(i,s,0);
if(f[i]==len)
add(i+n,t,1),add(t,i+n,0);
}
for(register int i=1;i<n;++i)
for(register int j=i+1;j<=n;++j)
if(a[i]<=a[j]&&f[i]+1==f[j])
add(i+n,j,1),add(j,i+n,0);
nn=(n<<1)+2,maxflow=0;
ISAP();
write(maxflow),puts("");
add(1,1+n,inf),add(1+n,1,0);
add(s,1,inf),add(1,s,0);
if(f[n]==len)
{
add(n,n<<1,inf),add(n<<1,n,0);
add(n<<1,t,inf),add(t,n<<1,0);
}
ISAP();
write(maxflow);
return 0;
}

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

  1. luogu P2766 最长不下降子序列问题

    第一问可以直接DP来做,联想上一题,线性规划都可以化为网络流?我们可以借助第一问的DP数组,来建立第二问第三问的网络流图,考虑每一种可能,都是dp数组中满足num[i]>=num[j]& ...

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

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

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

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

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

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

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

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

  6. P2766 最长不下降子序列问题 题解(网络流)

    题目链接 最长不下降子序列问题 解题思路 分成三小问解决. 第一小问,求\(LIS\),因为\(n<=500\),直接\(O(N^2)\)暴力求解即可. 第二三小问,建立模型用网络流求解. 对于 ...

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

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

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

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

  9. P2766 最长不下降子序列问题

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

随机推荐

  1. pytest 3.9在python 2.7下的一个bug

    最在在使用pytest,用的是pytest 3.9.3,python版本为2.7.10,但一直在使用时发现总提示 File "c:\python27\Lib\json\__init__.py ...

  2. 六种常见排序算法的java实现

    package edu.cn.ysw; //八种排序算法的实现与效率分析 /* * 内排序的种类: * 1.插入排序:直接插入排序.希尔排序. * 2.选择排序:简单选择排序.堆排序. 3.交换排序: ...

  3. Java课程课后作业02之动手动脑

    一.编写一个方法,使用以上算法生成指定数目(比如1000个)的随机整数 数学算法原理: 可以使用的方法:Math中的random类以及random类,区别:Math中的random类只能用于生成随机数 ...

  4. Lucene入门学习

    技术原理: 开发环境: lucene包:分词包,核心包,高亮显示(highlight和memory),查询包.(下载请到官网去查看,如若下载其他版本,请看我的上篇文档,在luke里面) 原文文档: 入 ...

  5. Oracle课程档案,第二天

    salary:工资 order by:排序 desc:降序 hire:雇佣 单行函数 一周有七天 一月不一定只有30天 trunc:截取 dual:空表 last:最后 month:月份 round: ...

  6. kafka的一些参数

    参考文档: https://blog.csdn.net/fengzheku/article/details/50585972 http://kafka.apache.org/documentation ...

  7. EasyUI combogrid/combobox过滤时限制只能选择现有项

    在使用EasyUI的combogrid时可以通过输入进行过滤,达到快速选择的目的,但是手工输入不存在的项也不会出错,结果提交到数据库后就会产生错误. 比如idField是int型的,输入的数据通过是检 ...

  8. (二)juc线程高级特性——CountDownLatch / Callable / Lock

    5. CountDownLatch 闭锁 Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器的性能. CountDownLatch 一个同步辅助类, ...

  9. C++ 11 多线程下std::unique_lock与std::lock_guard的区别和用法

    这里主要介绍std::unique_lock与std::lock_guard的区别用法 先说简单的 一.std::lock_guard的用法 std::lock_guard其实就是简单的RAII封装, ...

  10. centos6多实例安装mysql

    基本环境:setenforce 0service iptables stop yum install cmake libaio-devel ncurses-devel -yyum install gc ...