LOJ #3220. 「PA 2019」Terytoria(随机染色或线段树)

https://loj.ac/problem/3220

题解:

两维独立。

因为每个区间都是取或者取补集,所以枚举一个一定选点,就知道每个区间怎么选了。

这是\(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);
}
posted @ 2020-06-02 21:36  Cold_Chair  阅读(252)  评论(0编辑  收藏  举报