P2766 最长不下降子序列问题

考虑我们是如何\(dp\)这个\(LIS\)的。

我们是倒着推,设置\(dp(i)\)代表以\(i\)为起点的\(LIS\)是多少。转移太显然了

\[dp(i)=max\{dp(j)\}+1,data[i]\le data[j]
\]

想一想一个合法的\(LIS\)方案代表着什么,代表着它是由这个式子一个一个推出来的。

考虑一个数字只能用一次,那么我们直接拆成两个点\(v_0,v_1\)分别代表一个数字的入度和出度,连一条\(v_1v_2,cap=1\)的边。这样就模拟了一个数字可以被前面多个都相中但是只能往后面相中一个的要求。

考虑如何构造方案,这个东西是个灵感,就是还原\(dp\)的过程,这样就可以得到合法方案。

模型这样建立

\[(i_0,i_1,1)
\\
(S,i_0,inf),dp(i)=1
\\
(i_1,T,inf),dp(k)=ans
\]

这样就好了。

实际上,这样建模体现了"且"的关系,这种建模方式在以后可能大有用处。

#include<bits/stdc++.h>

using namespace std;typedef long long ll;
#define DRP(t,a,b) for(register int t=(a),edd=(b);t>=edd;--t)
#define RP(t,a,b) for(register int t=(a),edd=(b);t<=edd;++t)
#define ERP(t,a) for(register int t=head[a];t!=-1;t=e[t].nx)
#define midd register int mid=(l+r)>>1
#define TMP template < class ccf >
#define lef l,mid,pos<<1
#define rgt mid+1,r,pos<<1|1
#define pushup(pos) (seg[pos]=seg[pos<<1]+seg[pos<<1|1])
TMP inline ccf qr(ccf b){
register char c=getchar();register int q=1;register ccf x=0;
while(c<48||c>57)q=c==45?-1:q,c=getchar();
while(c>=48&&c<=57)x=x*10+c-48,c=getchar();
return q==-1?-x:x;}
TMP inline ccf Max(ccf a,ccf b){return a<b?b:a;}
TMP inline ccf Min(ccf a,ccf b){return a<b?a:b;}
TMP inline ccf Max(ccf a,ccf b,ccf c){return Max(a,Max(b,c));}
TMP inline ccf Min(ccf a,ccf b,ccf c){return Min(a,Min(b,c));}
TMP inline void READ(ccf* _arr,int _n){RP(t,1,_n)_arr[t]=qr((ccf)1);}
//----------------------template&IO--------------------------- const int maxn=5e2+15;
const int maxm=maxn<<3;
int dp[maxn];
int data[maxn];
const int inf=0x3f3f3f3f;
int n,S,T;
struct E{
int to,w,nx;
}e[maxm<<1],tmp[maxm<<1];
int cnt(-1);
int head[maxm];
int id[maxn][2];
int sz;
int ans1,ans2,ans3;
int d[maxm];
int cur[maxm]; inline void add(int fr,int to,int w,bool f){
e[++cnt]=(E){to,w,head[fr]};head[fr]=cnt;
if(f) add(to,fr,0,0);
} queue < int > q;
inline bool bfs(){
while(not q.empty()) q.pop();
RP(t,1,sz) cur[t]=head[t],d[t]=inf+1;
d[S]=1;q.push(S);
while(not q.empty()){
register int now=q.front();q.pop();
if(now==T) break;
ERP(t,now){
if(d[e[t].to]>d[now]+1&&e[t].w>0){
d[e[t].to]=d[now]+1;
q.push(e[t].to);
}
}
}
return d[T]<inf;
} int dfs(int now,int fl){
if(now==T||!fl) return fl;
register int ret=0;
for(register int t=cur[now],en;t!=-1;t=e[t].nx){
cur[now]=t;
if(d[e[t].to]==d[now]+1){
en=dfs(e[t].to,Min(fl,e[t].w));
if(en){e[t].w-=en;e[t^1].w+=en;fl-=en;ret+=en;}
if(not fl)break;
}
}return ret;
} inline void dinic(int& ret){while(bfs()) ret+=dfs(S,inf);} int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
memset(head,-1,sizeof head);
n=qr(1);
READ(data,n);
RP(t,1,n) dp[t]=1;ans1=1;
DRP(t,n,1) RP(i,t+1,n) if(data[t]<=data[i]) ans1=Max((dp[t]=Max(dp[t],dp[i]+1)),ans1);
S=++sz;T=++sz;
DRP(t,n,1){
id[t][0]=++sz;id[t][1]=++sz;
add(id[t][0],id[t][1],1,1);
if(dp[t]==1){add(id[t][1],T,inf,1);}
if(dp[t]==ans1){add(S,id[t][0],inf,1);}
RP(i,t+1,n) if(data[i]>=data[t]&&dp[i]+1==dp[t]) add(id[t][1],id[i][0],1,1);
}
RP(t,0,cnt) tmp[t]=e[t];
dinic(ans2);
RP(t,0,cnt) e[t]=tmp[t];
add(id[1][0],id[1][1],inf,1);
add(id[n][0],id[n][1],inf,1);
dinic(ans3);
if(ans1==1) ans2=ans3=n;
printf("%d\n%d\n%d\n",ans1,ans2,ans3);
return 0;
}

[**P2766** 最长不下降子序列问题](https://www.luogu.org/problemnew/show/P2766)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  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. @总结 - 2@ 位运算卷积/子集卷积 —— FWT/FMT

    目录 @0 - 参考资料@ @1 - 异或卷积概念及性质@ @2 - 快速沃尔什正变换(异或)@ @3 - 快速沃尔什逆变换(异或)@ @4 - 与卷积.或卷积@ @5 - 参考代码实现@ @6 - ...

  2. HDFS概念名称节点和数据节点-名称节点

  3. @总结 - 10@ Miller-Rabin素性测试与Pollard-Rho因数分解

    目录 @1 - 素性测试:Miller-Rabin算法@ @1.1 - 算法来源@ @1.2 - 算法描述@ @1.3 - 算法实现@ @2 - 因数分解:Pollard-Rho算法@ @2.0 - ...

  4. ras 加解密类,支持截取

    class RsaEncrypt{ private $_privateKey = false; private $_publicKey = false; /** * 私钥解密 * @param $da ...

  5. flowable笔记 - 简单的通用流程

    简介 通用流程可以用于一些基本的申请,例如请假.加班. 大致过程是: 1. 创建申请 2. 分配给审批人(需要审批人列表,当前审批人) -> 有下一个审批人 -> 3 -> 无 -& ...

  6. Linux环境下第一次提交项目

    Linux环境下第一次提交项目: vi 日记 新增一个文件名为“日记”的文件 git status 工作区的状态 git add 日记 建立跟踪 git commit 提交变更 ----------- ...

  7. 【原生JS】图片预加载之有序预加载

    <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...

  8. jackson java转json hibernate懒加载造成的无限递归问题

    @JsonIgnore @JsonFilter @JsonBackReference @JsonManagedReference @JsonIgnoreProperties jackson中的@Jso ...

  9. java接口的使用

    格式:public class SubImpl  extends Super  implements IA,IB 接口可以多继承,但是只能继承接口,不能继承类. 实现接口(支持多实现) [修饰符] c ...

  10. phpStudy中升级MySQL版本到5.7.17的方法步骤

    http://www.jb51.net/article/120263.htm 前言 今天在工作发现一个错误,在往本地导数据表的时候老是报错: ? 1 [Err] 1294 - Invalid ON U ...