2023牛客多校第九场 - E I

比赛地址:传送门
赛时实际上就过了签到题,呜呜~
E 思维题
I 思维题

E Puzzle: Square Jam

题意

思路
每次取最小的边,辗转相减即可

代码

void solve(){
	int n, m;
	cin >> n >> m;
	vector<tuple<int, int, int>> ans;
	ll res = n * m, x = 0, y = 0, l;
	while(res){
		l = min(n - x, m - y);
		ans.push_back(make_tuple(x, y, l));
		if(n - x < m - y){
			y += n - x;
		}else{
			x += m - y;
		}
		res = (n - x) * (m - y);
	}
	cout << "YES\n" << ans.size() << '\n';
	for(auto [x, y, z] : ans){
		cout << x <<' ' << y << ' ' << z << '\n';
	}
	return ;
}

I Non-Puzzle: Segment Pair

题意
给定 n 对区间,你可以在每一对区间里面任选一个区间,若这种选法所得的 n 个区间的交集不为空,那么这就是一个合法的选择区间的方式
问你选择合法区间的方式的个数模 $10^9 + 7 $

思路
思路来源

考虑所有点对于答案的贡献,对于每个区间仅让一个点对答案产生贡献
先计算出所有合法点对于答案的总贡献,再将所有给定区间的左端点均 + 1,再计算修改后的区间的赘余贡献,用前面算出的总贡献减去赘余贡献即为最终的答案

利用 dsu 压缩路径,利用差分数组统计重复选择

详见代码

代码

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 5e5 + 5, inf = 0x3f3f3f3f, mod = 1e9 + 7;
int n;
vector<array<int, 4>> seg(maxm);

ll pw2[maxm];
void pre(){
	pw2[0] = 1;
	for(int i = 1; i < maxm; ++ i){
		pw2[i] = pw2[i - 1] * 2 % mod;
	}
	return ;
}

struct DSU{
	int num;
	vector<int> fa;
	DSU(int x = maxm) : num(x), fa(x + 1){
		for(int i = 0; i <= x; ++ i) fa[i] = i;
	}
	int findfa(int x){//迭代实现,不压缩路径,用于数范围大时
		while (x != fa[x]) x = fa[x] = fa[fa[x]];
		return x;
	}
	// int findfa(int x){ return fa[x] == x ? x : fa[x] = findfa(fa[x]); }//递归实现,压缩路径
	void merge(int u, int v){
		fa[findfa(u)] = findfa(v); return ;
	}
	bool same(int u, int v){ return findfa(u) == findfa(v); }
};

ll calc(){
	vector<bool> ok(maxm, true);
	vector<int> cnt(maxm, 0);
	DSU dsu(maxm);
	for(int i = 0; i < n; ++ i){
		auto &[l1, r1, l2, r2] = seg[i];
		for(int j = dsu.findfa(1); j < l1; j = dsu.findfa(j)){
			ok[j] = 0;
			dsu.merge(j, j + 1);
		}
		for(int j = dsu.findfa(max(r1, r2) + 1); j <= 5e5; j = dsu.findfa(j)){
			ok[j] = 0;
			dsu.merge(j, j + 1);
		}
		if(l2 > r1){
			for(int j = dsu.findfa(r1 + 1); j < l2; j = dsu.findfa(j)){
				ok[j] = 0;
				dsu.merge(j, j + 1);
			}
		}
		int ml = max(l1, l2), nr = min(r1, r2);
		if(ml <= nr){
			++ cnt[ml]; -- cnt[nr + 1];
		}
	}
	for(int i = 1; i <= 5e5; ++ i) cnt[i] += cnt[i - 1];
	ll res = 0;
	for(int i = 1; i <= 5e5; ++ i){
		if(ok[i]){
			res += pw2[cnt[i]];
			res %= mod;
		}
	}
	return res;
}

void solve(){
	pre();
	cin >> n;
	for(int i = 0; i < n; ++ i){
		auto &[l1, r1, l2, r2] = seg[i];
		cin >> l1 >> r1 >> l2 >> r2;
		if(l1 > l2){
			swap(l1, l2);
			swap(r1, r2);
		}
	}
	ll ans = calc();
	for(int i = 0; i < n; ++ i){
		auto &[l1, r1, l2, r2] = seg[i];
		++ l1; ++ l2;
	}
	ans = (mod + ans - calc()) % mod;
	cout << ans << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int _ = 1;
	// cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}
posted on 2023-08-14 19:34  Qiansui  阅读(13)  评论(0编辑  收藏  举报