原题传送门

实际还是比较套路的建图

先暴力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. MapReduce Map数 reduce数设置

    JobConf.setNumMapTasks(n)是有意义的,结合block size会具体影响到map任务的个数,详见FileInputFormat.getSplits源码.假设没有设置mapred ...

  2. poj2251_kuagnbin带你飞专题一

    Dungeon Master Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32684   Accepted: 12529 ...

  3. Linux 的基本操作(系统的安装)

    操作系统的安装: 操作系统的安装 这次安装系统也是基于CentOS的安装.把光盘插入光驱,设置bios光驱启动.进入光盘的欢迎界面. 其中有两个选项,可以直接按回车,也可以在当前界面下输入 linux ...

  4. weblogic反序列化漏洞CVE-2018-2628-批量检测脚本

    #coding=utf-8 import socket import time import re,os,sys,codecs type = 'utf-8' reload(sys) sys.setde ...

  5. jenkins启动java项目的jar包总是退出

    参考文档: https://www.cnblogs.com/DFX339/p/8241253.htmlhttps://blog.csdn.net/windanchaos/article/details ...

  6. Java ee第一周的作业

    这学期目标:对Java ee 进行一定程度的学习,希望最后自己能尽可能掌握Java ee的知识 企业及应用的特点:企业级的应用通常比较庞大,而且其中的数据需要保密. Java ee 框架图

  7. 多线程Thread

    多线程的意义 使用多线程可以充分利用CPU资源.提高CPU的使用率,采用多线程的方式去同时完成几件事情而不互相干扰.在处理大量的IO操作或处理的情况需要花费大量的时间时(如:读写文件,视频图像的采集, ...

  8. SQLite multiple threads

    const int loops = 1000; public void DatabaseThreadSafetyTest() { var backgroundThread = new Thread(n ...

  9. 细说flask数据库迁移

    什么情况下要用数据库迁移? 在开发过程中,需要修改数据库模型,而且还要在修改之后更新数据库.最直接的方式就是删除旧表,但这样会丢失数据. 更好的解决办法是使用数据库迁移框架,它可以追踪数据库模式的变化 ...

  10. ssh防止暴力破解之fail2ban

    1.利用sshd服务本身防止暴力破解 2.sshd服务防止暴力破解和fail2ban使用方法 先说说一般的防范措施: 方法1: 1.密码足够复杂: 密码的长度要大于8位最好大于14位.密码的复杂度是密 ...