SequenceTime
limit:2000/1000 MS (java/others) Memory limit:32768/32768 K (java/others)
Total submission (s): 1666 Accepted Submission (s): 614
Problem Descriptionthere is a sequence X (i.e. x[1], x[2], ..., x[n]). We define increasing subsequence of X
As X[i1], X[i2],..., X[ik], which satisfies follow conditions:
1) X[i1] < X[i2],..., <x[ik];
2) 1<=i1 < i2,..., <ik<=n
As an excellent program designer, you must know how to find the maximum length of the
Increasing sequense, which is defined as S. Now, the next question are how many increasing
Subsequence with S-length can-find out from the sequence X.
For example, in one case, if s = 3, and you can find out 2 such subsequence A and B from X.
1) A = A1, A2, A3. B = B1, B2, B3.
2)Each ai or bj (i,j = chose) can is only a once at the most.
Now, the question is:
1) Find The maximum length of increasing subsequence of X (i.e. s).
2) Find the number of increasing subsequence with s-length under conditions described (i.e. num).
Inputthe input file has many cases. Each case would give a integer number n.the next line would
have n numbers.
Outputthe output has both line. The first line is S and second are Num.
Sample Input
43 6 2 5
Sample Output
22
Source2011 multi-university Training Contest 16-host by Tju There are two solutions to this question:
Fang Yi: dp+ Max Stream (the method I used)
Square Two: thinking: You can use the N*log (n) method to find the longest ascending subsequence, then delete the original array of these numbers, and then the longest ascending subsequence (if the length is reduced, then exit directly).
Test instructions: Give a sequence x (X[1], x[2], .... x[n]), the number is n. The length of the longest increment subsequence, and the number of the longest increment subsequence. Requirements: 1): X[i1] < X[i2],..., <x[ik]; (1<=i1 < i2,..., <ik<=n) 2): Each number can only be used once.
Problem solving: For the first question: the length of the longest increment sub-sequence ans is good to ask. Now for the second question, let's write down where each number belongs (that is, the length) when the longest increment subsequence is taken. Let's make a hypothesis: if a number num in the 2nd position of the record, and Num is the minimum, can find a length of ans the longest increment sub-sequence, then we can add a number (1th position number) to this sequence, the longest increment subsequence length is ans+1, because ans < ans +1, so the length of the longest increment subsequence as previously calculated ans contradiction. So the hypothesis is not tenable.
Conclusion: The starting number of a maximum increment subsequence must begin with the number in the 1th position. This is the most important reason why the maximum flow is used to solve the problem.
Map: (1) The first one as a point, and then each point I split into two points to build an edge: I--and (I+n) Contents 1 (After the break, I only can not enter the point, I+n Point only out, in addition to their own side). (2) The source point s=0 and the 1th position of each point I built an edge capacity of 1:s-->i. (3) Each ans position of each point with the meeting point t = 2*n+1 to build a side capacity of 1: (I+n)-->t. (4) The length of the point U of the first Len and the point of the len+1 length are constructed with a side capacity of 1. Meet the requirements: test instructions in 1) and 2).
#include <stdio.h> #include <string.h> #include <queue> #include <vector> #include < algorithm>using namespace std; #define Captype intconst int maxn = 100010; Total number of points const int MAXM = 400010; Total number of edges const int INF = 1<<30;struct edg{int to,next; Captype Cap,flow;} Edg[maxm];int Eid,head[maxn];int GAP[MAXN]; The number of points for each distance (or can be considered a height) int DIS[MAXN]; The shortest distance from each point to the end Enode int CUR[MAXN]; Cur[u] indicates that from the U point can flow through the cur[u] number side int pre[maxn];void init () {eid=0; memset (head,-1,sizeof (Head));} There are three parameters to the edge, 4 parameters void addedg (int u,int v,captype c,captype rc=0) without a forward edge {edg[eid].to=v; edg[eid].next=head[u]; Edg[eid].cap=c; edg[eid].flow=0; head[u]=eid++; Edg[eid].to=u; EDG[EID].NEXT=HEAD[V]; EDG[EID].CAP=RC; edg[eid].flow=0; head[v]=eid++;} Captype maxflow_sap (int snode,int enode, int n) {//n is the total number of points including the source and sink points, this must be noted memset (Gap,0,sizeof (GAP)); memset (dis,0,sizeof (dis)); memcpy (cur,head,sizeof (head)); Pre[snode] =-1; Gap[0]=n; Captype ans=0; Max Stream int U=sNode; while (dis[snode]<n) {//determines from SNode point there is no flow to the next adjacent point if (u==enode) {//Find a way to add flow captype min=inf; int inser; for (int i=pre[u]; i!=-1; i=pre[edg[i^1].to])//To find the maximum amount of traffic Min if (min>edg[i].cap-edg[i].flow) { Min=edg[i].cap-edg[i].flow; Inser=i; } for (int i=pre[u]; i!=-1; i=pre[edg[i^1].to]) {edg[i].flow+=min; Edg[i^1].flow-=min; Flow of the side that can be recycled} ans+=min; u=edg[inser^1].to; Continue } bool flag = FALSE; It is possible to determine whether an int v can flow toward the neighboring point from the U point; for (int i=cur[u]; i!=-1; i=edg[i].next) {v=edg[i].to; if (edg[i].cap-edg[i].flow>0 && dis[u]==dis[v]+1) {flag=true; Cur[u]=pre[v]=i; Break }} if (flag) {u=v; Continue }//If a flow adjacent point is not found above, then the distance from the starting point U (which can also be considered a height) is adjacentThe minimum distance of the flow point is +1 int mind= n; for (int i=head[u]; i!=-1; i=edg[i].next) if (edg[i].cap-edg[i].flow>0 && mind>dis[edg[i].to]) { MIND=DIS[EDG[I].TO]; Cur[u]=i; } gap[dis[u]]--; if (gap[dis[u]]==0) return ans; When Dis[u] The point of this distance is gone, it is impossible to find an augmented stream path from the source point//Because there is only one distance from the sink point to the current point, then from the source point to the sink point must pass the current point, but the current point is not able to find Can flow to the point, then the inevitable flow of dis[u]=mind+1;//if a stream of adjacent points is found, the distance is the distance of the adjacent point +1, if not found, then the n+1 gap[dis[u]]++; if (U!=snode) u=edg[pre[u]^1].to; Return an Edge} return ans; int BinarySearch (int* dp, int num, int ans) {int l=1, r = ans, mid; while (l<=r) {mid= (l+r) >>1; if (dp[mid]>=num) r = mid-1; else l=mid+1; } return L;} int main () {int n, NUM[MAXN], DP[MAXN]; while (scanf ("%d", &n) >0) {for (int i=1; i<= n; i++) scanf ("%d", &num[i]), dp[i]= INF; int ans=0; The length of the longest increment sub-sequence vector<vector<int> >vct; VCT = vector<vector<int> > (n,vector<int> (0,0)); for (int i=1; i<= n; i++) {int len= binarysearch (Dp,num[i],ans); Vct[len].push_back (i); if (Dp[len]>num[i]) dp[len]=num[i]; if (Ans<len) Ans=len; } init (); int s = 0, t = 2*n+1; for (int i=1; i<=n; i++)//split, self-point as an edge, each point can only be used once, so the capacity is 1 addedg (i, i+n, 1); for (int i=vct[1].size ()-1; i>=0; i--) addedg (S, Vct[1][i], 1); for (int i=vct[ans].size ()-1; i>=0; i--) addedg (Vct[ans][i]+n, T, 1); for (int len = 1, len<ans; len++) for (int i = Vct[len].size ()-1; i>=0; i--) {int u=vct[len][i]; for (int j = vct[len+1].size ()-1; j>=0; j--) {int v=vct[len+1][j]; if (U > v) break; If the V position is in front of the U position, it is not satisfied: 1<=i1 < I2,..., <ik<=n if (num[u]>=num[v]) continue; ADDEDG (U+n, V, 1); }} int K=maxflow_sap (S, T, t+1); The number of longest increment subsequence, quite looking for the number of (s-->t) road, each side can only be used once printf ("%d\n%d\n", ans,k); }}
HDU 3998 Sequence (longest increment sub-sequence + Max stream SAP, split method) Classic