P2766 最长不下降子序列问题
Posted zhltao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2766 最长不下降子序列问题相关的知识,希望对你有一定的参考价值。
序
我学oi是为了什么呢?
wjsjdnghnhzyqw
正文
话说,这个题的第一问不就是送的吗。求一个 LIS ,在数据量不大的时候,做一个朴素的 (n^2) ,就好了完全没必要用维护最后一个的 (n log n)
然后,我想的就是如何建图,话说其实第二问的做出来了,第三问不就是送的吗
我们来正经的说说,这个题怎么做
先是因为每个数只能用一次,然后,就考虑拆点
- because 我们要统计的是 LIS ,所以有在 (i>j , f[j]==f[i]+1 , a[j]<=a[i]) 时可以连一条 (j->i flow=1)的边,注意后面的点连前面的点。其实去所谓
我们对于 f[i]=1,f[i]=ans 的点分别连向 s 和 t
之后找猫画虎的改动一个地方就可以写出第三问
然后,你可以得到一个74pts代码
/* make by ltao */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <time.h>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <algorithm>
#include <list>
#include <map>
#include <vector>
#include <fstream>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define inf 1e5
#define sz 666666
#define fake int
#define get() getchar()
using namespace std;
int read(){
int x=0;char ch=get();bool f=0;
while(ch<'0'||ch>'9'){
if(ch=='-') f=1;
ch=get();
}
while(ch<='9'&&ch>='0'){
x=(x<<1)+(x<<3)+(ch-'0');
ch=get();
}
return f?-x:x;
}
const int Maxn=1e4+11,Maxm=2*1e5+111;
int n,a[Maxn],h[Maxn],s,t,cnt,f[Maxn],maxflow,ans,dep[Maxn],cur[Maxn];
struct Edge{
int to,flow,lac;
void insert(int x,int y,int z){
to=y;
lac=h[x];
h[x]=cnt++;
flow=z;
}
}edge[Maxm];
bool bfs(int s,int t){
queue<int> q;q.push(s);
memset(dep,-1,sizeof dep);dep[s]=0;
memcpy(cur,h,sizeof cur);
while(!q.empty()){
int fr=q.front();q.pop();
for(int i=h[fr];i!=-1;i=edge[i].lac){
int to=edge[i].to;
if(!edge[i].flow||dep[to]!=-1) continue;
dep[to]=dep[fr]+1;
q.push(to);
if(to==t){
while(!q.empty()) q.pop();
return 1;
}
}
}
return 0;
}
int dfs(int u,int min1){
if(u==t) return min1;
int sum=min1;
for(int i=cur[u];i!=-1;i=edge[i].lac){
int to=edge[i].to;
if(!edge[i].flow||dep[to]!=dep[u]+1) continue;
int ret=dfs(to,min(sum,edge[i].flow));
cur[u]=i;
edge[i].flow-=ret;edge[i^1].flow+=ret;sum-=ret;
if(!sum) break;
}
return min1-sum;
}
void Dinic(int s,int t){
while(bfs(s,t))
maxflow+=dfs(s,0x3f3f3f3f);
}
int main(){
freopen("c.in","r",stdin);
n=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++){
f[i]=1;
for(int j=1;j<i;j++)
if(a[j]<=a[i]) f[i]=max(f[i],f[j]+1);
ans=max(ans,f[i]);
}
printf("%d
",ans);s=0;t=n*2+1;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++)
if(f[i]==1) edge[cnt].insert(s,i*2-1,1),edge[cnt].insert(i*2-1,s,0);
else if(f[i]==ans) edge[cnt].insert(i*2,t,1),edge[cnt].insert(t,i*2,0);
for(int i=1;i<=n;i++)
edge[cnt].insert(i*2-1,i*2,1),edge[cnt].insert(i*2,i*2-1,0);
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
if(a[j]<=a[i]&&f[i]==f[j]+1){
edge[cnt].insert(j*2,i*2-1,1);
edge[cnt].insert(i*2-1,j*2,0);
}
Dinic(s,t);
printf("%d
",maxflow);
maxflow=0;memset(h,-1,sizeof h);cnt=0;
for(int i=1;i<=n;i++){
if(f[i]==1)
edge[cnt].insert(s,i*2-1,(i==1||i==n)?inf:1),edge[cnt].insert(i*2-1,s,0);
if(f[i]==ans)
edge[cnt].insert(i*2,t,(i==1||i==n)?inf:1),edge[cnt].insert(t,i*2,0);
}
for(int i=1;i<=n;i++)
edge[cnt].insert(i*2-1,i*2,(i==1||i==n)?inf:1),edge[cnt].insert(i*2,i*2-1,0);
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
if(a[j]<=a[i]&&f[i]==f[j]+1){
edge[cnt].insert(j*2,i*2-1,1);
edge[cnt].insert(i*2-1,j*2,0);
}
Dinic(s,t);
printf("%d",maxflow);
return 0;
}
因为你忘考虑 ans=1 的情况了。。
所以我们在此处加上特判
if(ans==1){
printf("%d
%d",n,n);
return 0;
}
然后,你就可以愉快的AC了,咕
嵬
上帝给了我oi,我要好好去珍惜
以上是关于P2766 最长不下降子序列问题的主要内容,如果未能解决你的问题,请参考以下文章