1. 程式人生 > >loj6005「網路流 24 題」最長遞增子序列(dp+最大流)

loj6005「網路流 24 題」最長遞增子序列(dp+最大流)

首先第一問就是dp求就好啦,寫了nlogn的。
現在我們已經有了dp[i],表示以第i個數結尾的lis是多長。考慮如何建圖實現第二問的限制,把每個點拆成兩點,建邊,容量為1,這樣就滿足了每個點最多被經過一次,然後源點向所有dp[i]為1的點建邊,容量為1,所有dp[i]==ans的點向T建邊,容量為1,對於每一個i,向所有能接在他後面的數j建邊,容量為1。(因為會有相等的,所以一定要嚴格滿足dp[i]+1=dp[j])。然後跑最大流即可。對於第三問,a1an可以隨便用,因此我們把這兩點內部的邊的容量改為inf即可。還有s向1,n向t的邊,如果有,也改成inf

#include <bits/stdc++.h>
using namespace std; #define ll long long #define N 510 #define inf 0x3f3f3f3f inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } int n,a[N],h[N<<1
],num=1,T=1001,lev[N<<1],d[N],dp[N],ans=0; struct edge{ int to,next,val; }data[N*N<<1]; inline void add(int x,int y,int val){ data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val; data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].val=0; } inline bool bfs(){ queue
<int>
q;memset(lev,0,sizeof(lev)); lev[0]=1;q.push(0); while(!q.empty()){ int x=q.front();q.pop(); for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(lev[y]||!data[i].val) continue; lev[y]=lev[x]+1;q.push(y); } }return lev[T]; } inline int dinic(int x,int low){ if(x==T) return low;int tmp=low; for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(lev[y]!=lev[x]+1||!data[i].val) continue; int res=dinic(y,min(tmp,data[i].val)); if(!res) lev[y]=0;tmp-=res;data[i].val-=res;data[i^1].val+=res; if(!tmp) return low; }return low-tmp; } int main(){ // freopen("a.in","r",stdin); n=read();for(int i=1;i<=n;++i) a[i]=read(); for(int i=1;i<=n;++i){ if(a[i]>=d[ans]) d[++ans]=a[i],dp[i]=ans; else{ int id=upper_bound(d+1,d+ans+1,a[i])-d; d[id]=a[i];dp[i]=id; } }printf("%d\n",ans); for(int i=1;i<=n;++i){ add(i,n+i,1);if(dp[i]==1) add(0,i,1);if(dp[i]==ans) add(n+i,T,1); for(int j=i+1;j<=n;++j) if(a[j]>=a[i]&&dp[j]==dp[i]+1) add(n+i,j,1); }int res=0;while(bfs()) res+=dinic(0,inf); printf("%d\n",res);num=1;memset(h,0,sizeof(h)); for(int i=1;i<=n;++i){ add(i,n+i,i==1||i==n?inf:1); if(dp[i]==1) add(0,i,i==1?inf:1); if(dp[i]==ans) add(n+i,T,i==n?inf:1); for(int j=i+1;j<=n;++j) if(a[j]>=a[i]&&dp[j]==dp[i]+1) add(n+i,j,1); }res=0;while(bfs()) res+=dinic(0,inf); printf("%d\n",res); }

相關推薦

loj6005網路 24 遞增序列dp+

首先第一問就是dp求就好啦,寫了nlogn的。 現在我們已經有了dp[i],表示以第i個數結尾的lis是多長。考慮如何建圖實現第二問的限制,把每個點拆成兩點,建邊,容量為1,這樣就滿足了每個點最多被經過一次,然後源點向所有dp[i]為1的點建邊,容量為1,所有

大子段和與遞增序列貪心與動態規劃

話不多說先上程式碼。。。。。  最大子段和 題目描述 給出一段序列,選出其中連續且非空的一段使得這段和最大。 輸入輸出格式 輸入格式:   第一行是一個正整數NNN,表示了序列的長度。 第二行包含NNN個絕對值不大於100001000010000的

遞增序列輸出遞增序列 及其長度

最長遞增子序列的解法有很多種,常用的有最長公共子序列法、動態規劃、記錄所有遞增序列長度最大值的方法。 最長公共子序列法:如例子中的陣列A{5,6, 7, 1, 2, 8},則我們排序該陣列得到陣

遞增序列 dp

給出長度為N的陣列,找出這個陣列的最長遞增子序列。(遞增子序列是指,子序列的元素是遞增的) 例如:5 1 6 8 2 4 5 10,最長遞增子序列是1 2 4 5 10。 Input 第1行:1個數N,N為序列的長度(2 <= N <= 50000) 第2 -

bzoj千計劃316:bzoj3173: [Tjoi2013]上升序列二分+樹狀陣列

#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 100001 #define lowbit(x) x&-x

遞增序列只求大小模板

初始化 輸入 div 分法 下界 ive tdi color ostream #include<iostream> #include<cstdio> #include<cstring> #include<algorithm>

dp-遞增序列 LIS

一個數 bsp 註意 str 只有一個 自然 end alt ace 首先引出一個例子 問題 :   給你一個長度為 6 的數組 , 數組元素為 { 1 ,4,5,6,2,3,8 } , 則其最長單調遞增子序列為 { 1 , 4 , 5 , 6 , 8 } , 並且長度

LCS求公共序列DP

遞推 劃分 get ima 維護 () arr har static 動態規劃並不是一種算法,而是一種解決問題的思路。典型的動態規劃問題,如最長公共子序列(LCS),最長單調子序列(LIS)等。 動態規劃分為四個步驟: 1.判斷問題是否具有最優子結構 這裏以LCS為例,X=

公共序列dp

比較 else pre turn 最長公共子序列 fin 規劃 字符 mem 求最長公共子序列,比較出兩個字符串的最長的序列。用動態規劃求解 1 #include <bits/stdc++.h> 2 #define N 10005 3 #define me

【BZOJ】3173: [Tjoi2013]上升序列樹狀數組

nss 貢獻 isp 轉化 復雜 src printf efi col 【題意】給定ai,將1~n從小到大插入到第ai個數字之後,求每次插入後的LIS長度。 【算法】樹狀數組||平衡樹 【題解】 這是樹狀數組的一個用法:O(n log n)尋找前綴和為k的最小位置。(當數列

動態規劃之遞增序列LIS

lib sca while -c -o 組成 describe log ret 在一個已知的序列{ a1,a2,……am}中,取出若幹數組成新的序列{ ai1, ai2,…… aim},其中下標 i1,i2, ……im保持遞增,即新數列中的各個數之間依舊保持原

上升序列dp

tps ann test case std intro lar ont sta into 鏈接:https://www.nowcoder.com/questionTerminal/d83721575bd4418eae76c916483493de來源:牛客網廣場上站著一支隊伍

51node 1134 遞增序列 數據結構

賦值 log 寫法 數字 name 內存 遞增 max scan 題意: 最長遞增子序列 思路: 普通的$O(n^2)$的會超時。。 然後在網上找到了另一種不是dp的寫法,膜拜一下,自己寫了一下解釋 來自:https://blog.csdn.net/Adusts/artic

遞增序列LIS和公共序列LCS

本文參考了《程式設計之美》、LeetCode中文題解以及部落格 https://blog.csdn.net/George__Yu/article/details/75896330 (LIS) https://blog.csdn.net/v_july_v/article/det

Prince and Princess—上升序列dp+二分查詢

題目連結:Prince and Princess UVA - 10635  題目大意: 給出n, m, k,求兩個長度分別為m + 1 和 k + 1且由1~n * n組成的序列的最長公共子序列長的。 解題思路: 按一般的o(n^2)的演算法超時了,所以

遞增序列LIS

本篇部落格主要講述什麼是最長公共子序列、求解最長公共子序列的思想,以及程式碼。 什麼是最長公共子序列?   給定一個長度為N的陣列,找出一個最長的單調自增子序列(不要求是連續的)。例如:6 5 7 8 4 3 9 1,這裡的最長遞增子序列是{ 6, 7, 8, 9}或者{

上升序列動態規劃,n²

package 實驗三; public class 最長上升子序列 { public static void main(String[] args) { E e=new E(); e.way(); e.show1(); e.show2(); e.sh

51Nod1134 遞增序列動歸

這道題用動歸的思想寫,在所給的陣列中找到最長遞增子序列。定義一個新的陣列存最長子序列,第i項如果大於陣列的最後一項,就加入陣列,如果小於,就用二分查詢找到第一個大於第i項的數,然後取代之。 lower

動態規劃遞增序列LIS、連續序列和、連續序列乘積

最長遞增子序列LIS 問題 給定一個長度為N的陣列,找出一個最長的單調自增子序列(不一定連續,但是順序不能亂)。例如:給定一個長度為6的陣列A{5, 6, 7, 1, 2, 8},則其最長的單調遞增子序列為{5,6,7,8},長度為4. 最長遞增子序列

遞增序列動態規劃

acc mage ios 數據 mes eth 遞增 整數 inpu 題目描述 有n個互不相同的整數an若存在一個數列bm其中對於任何1 < i < m滿足bi < bi+1 且 abi < abi+1則稱abn為an的一個遞增子序列試求出給