• 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("
    ")
    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
    ", ans1 * ans2);
    }
    
  • 相关阅读:
    【网络安全】telnet 登陆远程服务器
    【网络安全】window 快速搭建 ftp 及 多种访问方式
    科普:PCI-E插槽都有哪些样子?
    Memory及其controller芯片整体测试方案(下篇)
    Memory及其controller芯片整体测试方案(上篇)
    超通俗易懂科普:什么是光通信?
    PCB各层介绍及AD软件画PCB时的规则
    第一次接触FPGA至今,总结的宝贵经验
    嵌入式码农的10年Bug调试经验,值得一看
    做嵌入式驱动的,你一定要挺住!
  • 原文地址:https://www.cnblogs.com/coldchair/p/13033895.html
Copyright © 2020-2023  润新知