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
3 6 2 5
2 3
Description / Tips
n≤500
[Problem-solving ideas]
[Code]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }