LOJ #3220. 「PA 2019」Terytoria(随机染色或线段树)
题解:
两维独立。
因为每个区间都是取或者取补集,所以枚举一个一定选点,就知道每个区间怎么选了。
这是\(O(n^2)\)的。
发现从左往右枚举这个点,用线段树维护区间加减和最大值及数量就能做了。
时间复杂度:\(O(n~log~n)\)
然而有更加简单的方法,考虑对于一个区间\([x,y]\),给\([x,y]\)异或上一个随机数,最后看出现次数最多的数就是了。
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
const int N = 2e6 + 5;
int n, X, Y;
struct {
int x1, x2, y1, y2;
} a[N];
int b[N][2];
int d[N], d0;
int v0, v1[N], v2[N];
#define ull unsigned long long
ull rd() {
ull s = 0;
fo(i, 0, 5) s ^= ((ull) rand() << (15 * i));
return s;
}
int rk(int x) {
return lower_bound(v1 + 1, v1 + v0 + 1, x) - v1;
}
ull s[N];
const int M = 19260817;
struct hash {
int fi[M]; int d[N], d0;
int f[N], nt[N], tot; ull h[N];
int &operator[] (ull n) {
int y = n % M;
for(int p = fi[y]; p; p = nt[p])
if(h[p] == n) return f[p];
if(!fi[y]) d[++ d0] = y;
nt[++ tot] = fi[y], h[tot] = n, fi[y] = tot;
f[tot] = 0;
return f[tot];
}
void cl() {
fo(i, 1, d0) fi[d[i]] = 0,
d0 = 0;
}
} h;
ll solve(ll X) {
d[d0 = 1] = X;
fo(i, 1, n) {
b[i][0] ++;
d[++ d0] = b[i][0], d[++ d0] = b[i][1];
}
sort(d + 1, d + d0 + 1);
d0 = unique(d + 1, d + d0 + 1) - (d + 1);
v0 = 0;
fo(i, 1, d0) {
if(d[i] > d[i - 1] + 1) {
v1[++ v0] = d[i - 1] + 1;
v2[v0] = d[i] - d[i - 1] - 1;
}
v1[++ v0] = d[i];
v2[v0] = 1;
}
fo(i, 0, v0 + 1) s[i] = 0;
fo(i, 1, n) {
int x = rk(b[i][0]), y = rk(b[i][1]);
ull w = rd();
s[x] ^= w, s[y + 1] ^= w;
}
fo(i, 1, v0) s[i] ^= s[i - 1];
h.cl();
int mx = 0;
fo(i, 1, v0) {
h[s[i]] += v2[i];
mx = max(mx, h[s[i]]);
}
return mx;
}
int main() {
srand(19260817);
scanf("%d %d %d", &n, &X, &Y);
fo(i, 1, n) {
scanf("%d %d %d %d", &a[i].x1, &a[i].y1, &a[i].x2, &a[i].y2);
if(a[i].x1 > a[i].x2) swap(a[i].x1, a[i].x2);
if(a[i].y1 > a[i].y2) swap(a[i].y1, a[i].y2);
}
fo(i, 1, n) b[i][0] = a[i].x1, b[i][1] = a[i].x2;
ll ans1 = solve(X);
fo(i, 1, n) b[i][0] = a[i].y1, b[i][1] = a[i].y2;
ll ans2 = solve(Y);
pp("%lld\n", ans1 * ans2);
}
转载注意标注出处:
转自Cold_Chair的博客+原博客地址