1. 程式人生 > >bzoj3716/4251 [PA2014]Muzeum

bzoj3716/4251 [PA2014]Muzeum

using strong main getchar() 最大 sign sed 條件 com

傳送門:http://www.lydsy.com/JudgeOnline/problem.php?id=3716

http://www.lydsy.com/JudgeOnline/problem.php?id=4251

【題解】

非常妙的網絡流轉化

首先可以把警衛和寶藏看成最大權閉合子圖,用最小割的那種建模方法,即一開始加進來所有寶藏的價值

然後S連寶藏,警衛連T,有覆蓋關系的連inf

那麽就是一個最小割,復雜度是$O(maxflow(n+m, nm)$,顯然承受不了。

由於最小割和最大流等價,所以轉化最大流考慮。

問題變為

技術分享

那麽按x從大到小排序,每次2種操作:加入一個物品;有一個警衛可以噴水給所有y小於它物品。

顯然按照y從大到小噴最優,因為小的限制條件小。

用個set維護即可,註意set的時候lower_bound只能s.lower_bound(...),不能lower_bound(s.begin(), s.end(), ..)!!!

技術分享
# include <set>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef 
long long ll; typedef long double ld; typedef unsigned long long ull; const int N = 2e5 + 10; const int mod = 1e9+7; const ll inf = 5e18; inline int getint() { int x = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == -) f = 0; ch = getchar(); } while(isdigit(ch)) { x
= (x<<3) + (x<<1) + ch - 0; ch = getchar(); } return f ? x : -x; } int n, m, W, H; struct pa { ll x, y; int v; pa () {} pa (ll x, ll y, int v) : x(x), y(y), v(v) {} inline friend bool operator < (pa a, pa b) { return a.y < b.y || (a.y == b.y && a.x < b.x); } }a[N], b[N]; struct option { ll x, y; int v, op; option() {} option(int op, ll x, ll y, int v) : op(op), x(x), y(y), v(v) {} inline friend bool operator < (option a, option b) { return a.x < b.x || (a.x == b.x && a.op > b.op); } }p[N + N]; set<pa> s; set<pa>::iterator it; int main() { ll ans = 0; cin >> n >> m >> W >> H; for (int i=1; i<=n; ++i) { a[i].x = 1ll * H * getint(), a[i].y = 1ll * W * getint(), a[i].v = getint(); p[i] = option(1, a[i].x - a[i].y, a[i].x + a[i].y, a[i].v); ans += a[i].v; } for (int i=1; i<=m; ++i) { b[i].x = 1ll * H * getint(), b[i].y = 1ll * W * getint(), b[i].v = getint(); p[n + i] = option(2, b[i].x - b[i].y, b[i].x + b[i].y, b[i].v); } // maxflow int pn = n + m; sort(p+1, p+pn+1); s.clear(); for (int i=pn; i; --i) { if(p[i].op == 1) s.insert(pa(p[i].x, p[i].y, p[i].v)); else { int cv = p[i].v; pa r = pa(inf, p[i].y, cv), t; while(cv && s.size()) { it = s.upper_bound(r); if(it == s.begin()) break; --it; t = *it; s.erase(it); int tmp = min(t.v, cv); cv -= tmp, t.v -= tmp; ans -= tmp; if(t.v > 0) s.insert(t); } } } cout << ans; return 0; }
View Code

bzoj3716/4251 [PA2014]Muzeum