输入样例第一行包含两个数: 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)); }