P2766 最长不下降子序列问题

Posted zhltao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2766 最长不下降子序列问题相关的知识,希望对你有一定的参考价值。

我学oi是为了什么呢?

wjsjdnghnhzyqw

正文

话说,这个题的第一问不就是送的吗。求一个 LIS ,在数据量不大的时候,做一个朴素的 (n^2) ,就好了完全没必要用维护最后一个的 (n log n)

然后,我想的就是如何建图,话说其实第二问的做出来了,第三问不就是送的吗

我们来正经的说说,这个题怎么做

  1. 先是因为每个数只能用一次,然后,就考虑拆点

  2. because 我们要统计的是 LIS ,所以有在 (i>j , f[j]==f[i]+1 , a[j]<=a[i]) 时可以连一条 (j->i flow=1)的边,注意后面的点连前面的点。其实去所谓
  3. 我们对于 f[i]=1,f[i]=ans 的点分别连向 st

之后找猫画虎的改动一个地方就可以写出第三问

然后,你可以得到一个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 最长不下降子序列问题的主要内容,如果未能解决你的问题,请参考以下文章

P2766 [网络流24题]最长不下降子序列问题

P2766 最长不下降子序列问题

洛谷P2766 最长递增子序列问题

网络流24题之最长不下降子序列问题

浅谈最长不下降子序列与最长上升子序列

模板最长不下降子序列