輸入樣例第一行包含兩個數: n、 m, n 表示有 n 個房間以及 n 個須要被幹擾的設備。
接下來有 m 行, 描述可干擾關係。 每一行兩個數 a、 b 表示在房間 a 設置干擾裝置能夠干擾到設備 b。
接下來一行 n 個數,第 i 個數表示干擾第 i 個設備能獲得的報酬。
接下來一行 n 個數,第 i 個數表示在第 i 個房間設置裝置能獲得的經驗值。node
一個數表示皮爾斯能獲得的最大的金錢經驗和。數組
Sample Input3 3
1 1
1 3
3 2
1 2 3
1 2 3ide
7spa
Data Constraint對於 30%數據: 1 ≤ n ≤ 100
對於 100%數據: 1 ≤ n ≤ 100000, 0 ≤ m ≤ 500000, 0 ≤ Pi, Vi ≤ 1000code
今天的題好難啊!!!blog
這道題題意是:有一個二分圖,兩邊各有n個點,一共m條邊,選擇一些不相交的邊,獲得選擇的邊所鏈接兩個點的得分,每一個點最多隻有一條與之鏈接的邊被選擇,求最大的得分。圖片
顯然,暴力出一個DPf[i][j] = max{ f[i-1][k]} + vx[i] + vy[j] ip
觀察上面求最大值的部分,是一段連續的值,那麼明顯可使用線段樹或者樹狀數組快速求得。get
時間複雜度O(m * log n)string
代碼#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=511111; struct node { int x,y; }a[N]; int t[N],f[N],v[N],s[N]; int n,m; int read() { int x = 0; char ch = getchar(); while (ch < '0' || ch > '9') ch = getchar(); while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x; } bool cmp(node l,node r) { return l.x==r.x?l.y>r.y:l.x<r.x; } int use(int x) { int ans=0; for(int i=x; i; i-=i&(-i)) ans=max(ans,t[i]); return ans; } inline void add(int x,int val) { for(int i=x; i<=m; i+=i&(-i)) t[i]=max(val,t[i]); } int main() { freopen("4.in","r",stdin); freopen("text.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1; i<=m; i++) a[i].x=read(),a[i].y=read(); for(int i=1; i<=n; i++) s[i]=read(); for(int i=1; i<=n; i++) v[i]=read(); sort(a+1,a+m+1,cmp); for(int i=1; i<=m; i++) { f[a[i].y]=max(f[a[i].y],use(max(a[i].y-1,0))+s[a[i].y]+v[a[i].x]); add(a[i].y,f[a[i].y]); } printf("%d",use(m)); }