20250208

T1

洛谷 P5987 Terytoria

显然两维独立。对于一维的问题,求出所有区间包含等价类。然后只需要选权值最大的等价类即可。使用异或哈希求等价类,复杂度单 \(\log\)。

代码
#include <iostream>
#include <algorithm>
#include <string.h>
#include <random>
#include <time.h>
#include <vector>
#define int long long
using namespace std;
random_device rd;
mt19937_64 mtrand(rd());
char buf[1<<23],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 
template<typename T>void read(T&x){
    x=0;
    char c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
}
int n, m, K;
int val[1000005];
int v[1000005];
struct ds {
    pair<int, int> p[500005];
    int d[1000005], dcnt;
    int xv[1000005];
    int work(int n) {
        memset(xv, 0, sizeof xv);
        for (int i = 1; i <= K; i++) d[i] = p[i].first, d[i + K] = p[i].second;
        dcnt = K * 2;
        d[++dcnt] = 0, d[++dcnt] = n;
        sort(d + 1, d + dcnt + 1);
        dcnt = unique(d + 1, d + dcnt + 1) - d - 1;
        for (int i = 1; i <= K; i++) {
            p[i].first = lower_bound(d + 1, d + dcnt + 1, p[i].first) - d;
            p[i].second = lower_bound(d + 1, d + dcnt + 1, p[i].second) - d;
            xv[p[i].first] ^= val[i];
            xv[p[i].second] ^= val[i];
        }
        for (int i = 1; i < dcnt; i++) p[i] = make_pair(xv[i] ^= xv[i - 1], v[i] = d[i + 1] - d[i]);
        sort(p + 1, p + dcnt);
        int ret = 0;
        for (int i = 1; i < dcnt;) {
            int j = i, tmp = 0;
            while (j < dcnt && p[j].first == p[i].first) tmp += p[j].second, ++j;
            i = j;
            ret = max(ret, tmp);
        }
        return ret;
    }
} X;
int xx1[500005], yy1[500005];
int xx2[500005], yy2[500005];
signed main() {
    int ttt = clock();
    freopen("donuts.in", "r", stdin);
    freopen("donuts.out", "w", stdout);
    read(K), read(n), read(m);
    for (int i = 1; i <= K; i++) val[i] = mtrand();
    // cerr << "Fdsa\n";
    for (int i = 1; i <= K; i++) {
        read(xx1[i]), read(yy1[i]), read(xx2[i]), read(yy2[i]);
        (xx1[i] > xx2[i]) ? swap(xx1[i], xx2[i]) : void();
        (yy1[i] > yy2[i]) ? swap(yy1[i], yy2[i]) : void();
    }
    for (int i = 1; i <= K; i++) X.p[i] = make_pair(xx1[i], xx2[i]);
    int ax = X.work(n); 
    // cerr << ax << "\n";
    for (int i = 1; i <= K; i++) X.p[i] = make_pair(yy1[i], yy2[i]);
    cout << 1ll * ax * X.work(m) << "\n";
    cerr << (1.0 * clock() - ttt) / CLOCKS_PER_SEC << "\n";
    return 0;
}

T2

洛谷 P7425 机场

注意到一个飞机只会从廊桥换到摆渡车。先判掉无解,则一个飞机若换到摆渡车,就相当于让它直接起飞,因为反正后面也没用了。而如果一架飞机我们知道它要从廊桥换到摆渡车,则一定是在它在廊桥接完客之后直接把它扔到摆渡车,也就是让它起飞。这样就可以直接费用流建模了,对每个离散化之后的时刻和每个飞机建一个点即可。

代码
#include <iostream>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <queue>
#define int long long
using namespace std;
const int inf = 0x3f3f3f3f3f3f3f3f;
struct Cost_Flow {
    static const int N = 100005, M = 8000005;
    int n, S, T, c;
    int head[N], cur[N], nxt[M], to[M], cst[M], res[M], ecnt;
    int add(int u, int v, int x, int y) {
        to[++ecnt] = v, nxt[ecnt] = head[u], head[u] = ecnt, cst[ecnt] = y, res[ecnt] = x;
        to[++ecnt] = u, nxt[ecnt] = head[v], head[v] = ecnt, cst[ecnt] = -y, res[ecnt] = 0;
        return ecnt - 1;
    }
    int dist[N];
    bool inq[N], vis[N];
    queue<int> q;
    bool spfa() { // min cost
        q.push(S);
        memset(dist, 63, sizeof dist);
        dist[S] = 0;
        while (!q.empty()) {
            int x = q.front();
            q.pop();
            inq[x] = 0;
            for (int i = head[x]; i; i = nxt[i]) {
                int v = to[i];
                if (dist[v] > dist[x] + cst[i] && res[i]) {
                    dist[v] = dist[x] + cst[i];
                    if (!inq[v]) {
                        inq[v] = 1;
                        q.push(v);
                    }
                }
            }
        }
        return (dist[T] != dist[0]);
    }
    int dfs(int x, int flow) {
        if (x == T) 
            return flow;
        vis[x] = 1;
        int ret = 0;
        for (int i = cur[x]; i && flow; i = nxt[i]) {
            cur[x] = i;
            int v = to[i];
            if (dist[v] == dist[x] + cst[i] && res[i] && !vis[v]) {
                int tmp = dfs(v, min(flow, res[i]));
                if (tmp) {
                    res[i] -= tmp;
                    res[i ^ 1] += tmp;
                    flow -= tmp;
                    ret += tmp;
                    c += tmp * cst[i];
                }
            }
        }
        if (!ret) 
            dist[x] = inf;
        vis[x] = 0;
        return ret;
    }
    int dinic() {
        int ret = 0;
        while (spfa()) {
            for (int i = 1; i <= n; i++) cur[i] = head[i];
            ret += dfs(S, inf);
        }
        return ret;
    }
    void initialize(int nn, int ss, int tt) {
        n = nn, S = ss, T = tt;
        ecnt = 1, c = 0;
        for (int i = 0; i <= n; i++) head[i] = 0;
    }
} G;
int n, a, b;
long double coef;
int x[205], s[205], t[205];
int pre[405];
int d[405], dcnt;
signed main() {
    freopen("airport.in", "r", stdin);
    freopen("airport.out", "w", stdout);
    int tc;
    cin >> tc;
    while (tc--) {
        cin >> n >> a >> b >> coef;
        dcnt = n * 2;
        for (int i = 1; i <= n; i++) cin >> x[i] >> s[i] >> t[i], d[i] = s[i], d[i + n] = t[i];
        sort(d + 1, d + n * 2 + 1);
        dcnt = unique(d + 1, d + dcnt + 1) - d - 1;
        memset(pre, 0, sizeof pre);
        for (int i = 1; i <= n; i++) {
            s[i] = lower_bound(d + 1, d + dcnt + 1, s[i]) - d;
            t[i] = lower_bound(d + 1, d + dcnt + 1, t[i]) - d;
            pre[s[i]]++, pre[t[i]]--;
        }
        for (int i = 1; i <= dcnt; i++) pre[i] += pre[i - 1];
        bool no = 0;
        for (int i = 1; i <= dcnt; i++) {
            if (pre[i] > a + b) 
                no = 1;
        }
        if (no) {
            cout << "impossible\n";
            continue;
        }
        G.initialize(dcnt + n + 2, dcnt + n + 1, dcnt + n + 2);
        for (int i = 1; i <= n; i++) {
            G.add(G.S, s[i], 1, 0);
            G.add(s[i], i + dcnt, 1, x[i]);
            G.add(t[i], i + dcnt, 1, 0);
            G.add(s[i] + 1, i + dcnt, 1, floor(coef * x[i] + 0.00001));
            G.add(i + dcnt, G.T, 1, 0);
        }
        for (int i = 1; i < dcnt; i++) G.add(i, i + 1, a, 0);
        G.dinic();
        cout << G.c << "\n";
    }
    return 0;
}
posted @ 2025-02-09 18:49  forgotmyhandle  阅读(26)  评论(0)    收藏  举报