• LOJ3220「PA 2019」Terytoria【线段树,随机化】


    给定 (X imes Y) 的球形网格(上下、左右边界分别连通)和 (n) 个边平行于坐标轴的矩形的两个对顶点,求这些矩形交的面积的最大值。

    (nle 5cdot 10^5)(2le X,Yle 10^9)


    矩形有四种情况:两维取区间/取补,所以两维独立,分别做然后把答案乘起来即可。

    不容易发现,因为是选择一堆互补的区间交起来,所以只要选择一个点要求所有区间包含它就确定了决策,按顺序枚举这个点然后用线段树维护每个位置被包含的次数,若为 (n) 则属于区间交,时间复杂度 (O(nlog n))

    当然也可以用随机权值,对每个区间异或上 ([0,2^{64})) 的自然数,众数的出现次数就是答案,时间复杂度 (O( ext{Sorting}(n))),错误概率同生日碰撞。

    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    using namespace std;
    typedef unsigned long long LL;
    typedef pair<int, LL> pii;
    const int N = 1e6;
    template<typename T>
    void rd(T &x){
    	int ch = getchar(); x = 0;
    	for(;ch < '0' || ch > '9';ch = getchar());
    	for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
    }
    template<typename T>
    bool chmax(T &a, const T &b){if(a < b) return a = b, 1; return 0;}
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    int n, X, Y, a[2][N];
    pii b[N];
    int work(int *a, int X){
    	for(int i = 0;i < n;i += 2){
    		LL v = (LL)rng()<<32|rng();
    		b[i] = MP(a[i], v);
    		b[i+1] = MP(a[i+1], v);
    	}
    	LL now = 0; sort(b, b+n);
    	unordered_map<LL, int> ma;
    	ma[0] = b[0].fi; b[n].fi = X;
    	for(int i = 0;i < n;++ i){
    		now ^= b[i].se; ma[now] += b[i+1].fi - b[i].fi;
    	}
    	int ans = 0;
    	for(auto v : ma) chmax(ans, v.se);
    	return ans;
    }
    int main(){
    	rd(n); rd(X); rd(Y); n <<= 1;
    	for(int i = 0;i < n;++ i)
    		for(int j = 0;j < 2;++ j) rd(a[j][i]);
    	printf("%lld
    ", (LL)work(a[0],X)*work(a[1],Y));
    }
    
  • 相关阅读:
    Zookeeper 入门第一篇
    jmap命令
    Java中的原子操作类
    Fel表达式实践
    Fel表达式使用过程中需要注意的问题
    【luoguP1196】 [NOI2002]银河英雄传说--边带权并查集 ,
    【luoguP1955 】[NOI2015]程序自动分析--普通并查集
    【csp模拟赛2】 序列操作
    【csp模拟赛2】 爆搜 方格加数
    HZWER
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/14951496.html
Copyright © 2020-2023  润新知