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. async/await运用-前端表单弹窗验证同步书写方式(React)

    在前端项目中,我们经常会碰到这样的场景: 当前我们有一个表单需要填写,在完成表单填写后经过校验之后会弹出短信或者其他形式验证码,进行补充校验,然后一起提交给接口. 场景如下图: 当前为创建操作,编辑操 ...

  2. 深度学习——Xavier初始化方法

    “Xavier”初始化方法是一种很有效的神经网络初始化方法,方法来源于2010年的一篇论文<Understanding the difficulty of training deep feedf ...

  3. Core Data 数据出现Fault

    I am mapping Json Data from Server using Restkit and I am Displaying those data by fetching from db. ...

  4. oracle不明确的索引等级

    当ORACLE无法判断索引的等级高低差别,优化器将只使用一个索引,它就是在WHERE子句中被列在最前面的. 举例: DEPTNO上有一个非唯一性索引,EMP_CAT也有一个非唯一性索引. SELECT ...

  5. 各种浏览器的兼容css

    http://blog.csdn.net/wyx100/article/details/50450728 1.Mozilla内核[css]元素选择器{-moz-transition:运动的样式 持续时 ...

  6. HTML静态网页--JavaScript-语法

    1.基本数据类型: 字符串.小数.整数.日期时间.布尔型等. 2.变量: 都是通用类型var,可以随便存储其他类型的值,可以直接使用,不用定义,但习惯上定义.定义变量:var a:所有变量定义 都用v ...

  7. oracle merge into 新增或者修改

    merge into sn_balance b1 using(select 'admin' as userid,1 as type1 from dual) b2 on(b1.userid=b2.use ...

  8. PHP程序员技术职业生涯,你是如何规划的?

    职业规划是这样的 看到很多PHP程序员职业规划的文章,都是直接上来就提Linux.PHP.MySQL.Nginx.Redis.Memcache.jQuery这些,然后就直接上手搭环境.做项目,中级就是 ...

  9. npx cowsay 让动物说话~

      发现个好玩的东东, 忍不住想分享出来, 好可爱, 哈哈哈~~   node环境执行命令:    npm i cowsay -D npx cowsay hello! npx cowsay -f sh ...

  10. iptables [match] 常用封包匹配参数

    参数 -p, --protocol 范例 iptables -A INPUT -p tcp 说明 匹配通讯协议类型是否相符,可以使用 ! 运算符进行反向匹配,例如: -p !tcp 意思是指除 tcp ...