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])。然後跑最大流即可。對於第三問,
#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的一個遞增子序列試求出給