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;
}

浙公网安备 33010602011771号