zoukankan      html  css  js  c++  java
  • bzoj3716/4251 [PA2014]Muzeum

    传送门: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
  • 相关阅读:
    素敵な日本人 2-1
    十年目のバレンタインデー のほか
    水晶の数珠  3
    水晶の数珠  2
    STM32 USB HID BarCodeReader不兼容问题的解决
    水晶の数珠 1
    クリスマスミステリ 2
    クリスマスミステリ 1
    サファイア奇跡 3
    感悟成功
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3716.html
Copyright © 2011-2022 走看看