[P2766] does not drop the longest subsequence problem

Title Description

"Problem Description:

A given sequence of positive integers x1, ..., xn.

(1) calculate the maximum length decrease of sequence length s.

(2) calculate how many lengths can be taken up from a given sequence does not decrease as the sequence s.

(3) If allowing multiple sequence x1 and xn taken in, from the given sequence length of the maximum number of removable sequence s does not decrease.

<< programming tasks:

Computing tasks to complete the design of effective algorithm (1) (2) (3) proposed.

Input Format

Line 1 has a positive integer n, the length of a given sequence. The next line 1 has n positive integer n: x1, ..., xn.

Output Format

The first row is the longest sequence length does not fall s. Line 2 is the removable length s does not decrease the number of sub-sequences. Line 3 is to allow the use of removable x1 and xn when the sequence length is extracted several times s does not decrease the number of sequences.

Sample input and output

Input # 1
4
3 6 2 5
Output # 1
2
2
3

Description / Tips

n500

 


 

[Problem-solving ideas]

 

 

 

 

 

 

 

 

[Code]

#include<cstdio>
#include<queue>
#include<cstring>
#define ll int 
using namespace std;
const int MAXN = 5010;
const int MAXM = 200010;
const ll  INF = (1ll << 31) - 1;
struct note
{
    int to;
    int nt;
    int rev;
    ll cal;
};
struct edge
{
    note arr[MAXM];
    int siz;
    int maxn;
    int a[MAXN];
    int dp[MAXN];
    int  st[MAXN];
    int  dis[MAXN];
    int  cur[MAXN];
    int  depth[MAXN];
    int  top;
    int n, m, s, t;
    edge()
    {
        memset(st, -1, sizeof(st));
        memset(depth, -1, sizeof(depth));
        memset(dis, -1, sizeof(dis));
        top = 0;
    }
    void read()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
    }
    int LIS()
    {
        
        for (int i = 1; i <= n; i++)
            dp[i] = 1;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j < i; j++)
            {
                if (a[j] <= a[i])
                {
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
        maxn = -1;
        for (int i = 1; i <= n; i++)
            if (maxn < dp[i])
                maxn = dp[i];
        return maxn;
    }
    void build()
    {
        t = 2*n+2;
        for (int i = 1; i <= n; i++)
        {
            add(i, i + n, 1);
            if(dp[i]==1)
                add(0, i, 1);
            if (dp[i] == maxn)
                add(i + n, t, 1);
        }
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <i; j++)
                if (a[j] <= a[i] && dp[j] + 1 == dp[i])
                    add(j+n, i , 1);
        s = 0;
        siz = 2 * n+1;
    }
    bool dep()
    {
        queue<int> q;
        q.push(s);
        memset(depth, -1, sizeof(depth));
        depth[s] = 0;
        while (!q.empty())
        {
            int v = q.front(); q.pop();
            for (int i = st[v]; i != -1; i = arr[i].nt)
            {
                int to = arr[i].to;
                if (!arr[i].cal)
                    continue;
                if (depth[to] != -1)
                    continue;
                depth[to] = depth[v] + 1;
                q.push(to);
            }
        }
        return (depth[t] != -1);

    }
    void add(int x, int y, ll z)
    {
        top++; arr[top] = { y,st[x],top + 1,z }; st[x] = top;
        top++; arr[top] = { x,st[y],top - 1,0 }; st[y] = top;
    }
    ll dfs(int now, ll val)
    {
        if (now == t || !val)
            return val;
        ll flow = 0;
        for (int& i = cur[now]; i != -1; i = arr[i].nt)
        {
            int to = arr[i].to;
            if (depth[to] != depth[now] + 1)
                continue;
            ll f = dfs(to, min(arr[i].cal, val));
            if (!f || !arr[i].cal)
                continue;
            flow += f;
            arr[i].cal -= f;
            arr[arr[i].rev].cal += f;
            val -= f;
            if (!val)
                return flow;
        }
        return flow;
    }
    ll dinic()
    {
        ll flow = 0;
        ll f;
        while (dep())
        {
            for (int i = 0; i <= siz; i++)
                cur[i] = st[i];
            while (f = dfs(s, INF))
                flow += f;
        }
        return flow;
    }
};
edge road,tmp;
int main()
{
    road.read();
    //printf("**\n");
    printf("%d\n",road.LIS());
    //printf("**\n");
    //printf("\n");
    road.build();
    //printf("**\n");
    tmp = road;
    printf("%d\n", tmp.dinic());
    if(road.dp[1]==1)
    road.add(road.s, 1, INF);
    if(road.dp[road.n]==road.maxn)
    road.add(road.n * 2, road.t, INF);
    road.add(1, road.n + 1, INF);
    road.add(road.n, road.n * 2, INF);
    printf("%d", road.dinic());
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/rentu/p/11323873.html