\ (\ quad \) Once you know this question is a network stream, thinking it is a miss.
\ (\ Quad \) first with \ (O (^ n-2) \) DP obtains \ (DP \) and \ (S \) . Here \ (dp_i \) represents the \ ([1, i] \ ) last element in the range of \ (I \) does not decrease the length of the longest sequence.
for(int i = 1; i <= n; ++i)
for(int j = 0; j < i; ++j){
if(x[j] <= x[i])
dp[i] = max(dp[i], dp[j] + 1);
s = max(s, dp[i]);
}
\ (\ Quad \) \ (\ mathrm the I {.} \)
\ (\ qquad \) directly outputs \ (S \) can.
\ (\ Quad \) \ (\ mathrm {II.} \)
\ (\ qquad \) \ (\ FORALL I, J \) satisfies \ (i> j \) and \ (x_i \ GEQ x_j \) , even one from \ (r_j \) to \ (L_i \) , capacity \ (1 \) directed edge; \ (\ FORALL I \) satisfies \ (dp_i = 1 \) , even one from source to \ ( L_i \) , capacity \ (1 \) directed edge; \ (\ FORALL I \) satisfies \ (dp_i = S \) , even one from \ (r_i \) to sink, capacity \ (1 \ ) directed edge, \ (\ FORALL I \) , even from a \ (L_i \) to\ (r_i \) , capacity \ (1 \) directed edge. This figure is the maximum flow of the answer.
\ (\ Quad \) \ (\ mathrm {III.} \)
\ (\ qquad \) begins as all elements to this question can be repeatedly used, the tone for a long time - directly connected \ ((s, l_1 ) \) , \ ((L_1, R_1) \) , \ ((L_n, R_n) \) , \ ((R_n, T) \) capacity \ (+ \ infty \) directed to edge.
#include <cstdio>
#include <cstring>
#include <queue>
inline int max(const int& a, const int& b){
return a > b ? a : b;
}
inline int min(const int& a, const int& b){
return a < b ? a : b;
}
const int MAXN = 5e2 + 19, INF = 0x3f3f3f3f;
struct Edge{
int to, next, c;
}edge[MAXN * MAXN << 1];
int cnt = -1, head[MAXN << 1];
inline void add(int from, int to, int c){
edge[++cnt].to = to;
edge[cnt].c = c;
edge[cnt].next = head[from];
head[from] = cnt;
}
int n, x[MAXN], s;
int dep[MAXN << 1];
int bfs(void){
std::memset(dep, 0, sizeof(dep)); dep[0] = 1;
std::queue<int>q; q.push(0);
while(!q.empty()){
int node = q.front();
for(int i = head[node]; i != -1; i = edge[i].next)
if(!dep[edge[i].to] && edge[i].c)
dep[edge[i].to] = dep[node] + 1, q.push(edge[i].to);
q.pop();
}
return dep[n + n + 1];
}
int dfs(int node, int flow){
if(node == n + n + 1 || !flow)
return flow;
int stream = 0, f;
for(int i = head[node]; i != -1; i = edge[i].next)
if(dep[edge[i].to] == dep[node] + 1 && (f = dfs(edge[i].to, min(flow, edge[i].c)))){
flow -= f, stream += f;
edge[i].c -= f, edge[i ^ 1].c += f;
if(!flow)
break;
}
return stream;
}
int dinic(void){
int flow = 0;
while(bfs())
flow += dfs(0, INF);
return flow;
}
int dp[MAXN], ans;
int main(){
std::scanf("%d", &n);
for(int i = 1; i <= n; ++i)
std::scanf("%d", x + i);
for(int i = 1; i <= n; ++i)
for(int j = 0; j < i; ++j){
if(x[j] <= x[i])
dp[i] = max(dp[i], dp[j] + 1);
s = max(s, dp[i]);
}
std::printf("%d\n", s);
std::memset(head, -1, sizeof(head));
for(int i = 1; i <= n; ++i)
add(i, i + n, 1), add(i + n, i, 0);
for(int i = 1; i <= n; ++i){
if(dp[i] == 1)
add(0, i, 1), add(i, 0, 0);
for(int j = 1; j < i; ++j)
if(dp[i] == dp[j] + 1 && x[i] >= x[j])
add(j + n, i, 1), add(i, j + n, 0);
if(dp[i] == s)
add(i + n, n + n + 1, 1), add(n + n + 1, i + n, 0);
}
std::printf("%d\n", ans = dinic());
add(0, 1, INF), add(1, 0, 0), add(1, 1 + n, INF), add(1 + n, 1, 0);
if(dp[n] == s)
add(n, n + n, INF), add(n + n, n, 0), add(n + n, n + n + 1, INF), add(n + n + 1, n + n, 0);
std::printf("%d\n", ans + dinic());
return 0;
}
\ (\ quad \) there are a lot of weird data on this question Luo Gu, good Fana.