【GDKOI2015】看門狗

Description

這裏寫圖片描述

Input

輸入樣例第一行包含兩個數: n、 m, n 表示有 n 個房間以及 n 個須要被幹擾的設備。
接下來有 m 行, 描述可干擾關係。 每一行兩個數 a、 b 表示在房間 a 設置干擾裝置能夠干擾到設備 b。
接下來一行 n 個數,第 i 個數表示干擾第 i 個設備能獲得的報酬。
接下來一行 n 個數,第 i 個數表示在第 i 個房間設置裝置能獲得的經驗值。node

Output

一個數表示皮爾斯能獲得的最大的金錢經驗和。數組

Sample Input

3 3
1 1
1 3
3 2
1 2 3
1 2 3ide

Sample Output

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));
}
相關文章
相關標籤/搜索