Codeforces Round #791 (Div. 2) C Rooks Defenders 三种解法

这篇博客详细介绍了三种数据结构在解决实际问题中的应用。首先讲解了`lower_bound`函数在集合操作中的使用,接着探讨了树状数组在动态维护区间和查询中的效率,最后阐述了线段树如何高效地处理区间更新和查询。这些内容对于提升算法能力非常有帮助。
摘要由CSDN通过智能技术生成

题目链接

一.lower_bound 函数

#include<bits/stdc++.h>
using namespace std;
using namespace std;
typedef long long ll;
const ll inf = 0x3f3f3f3f3f3f3f3f;
set<int>s1;
set<int>s2;
int cntx[100007];
int cnty[100007];
void solve() {
	int n, q;
	cin >> n >> q;
	for (int i = 0; i <= n + 1; i++) {
		s1.insert(i);
		s2.insert(i);
	}
	while (q--) {
		int t;
		int x, y;
		scanf("%d", &t);
		if (t == 1) {
			scanf("%d %d", &x, &y);
			cntx[x]++;
			cnty[y]++;
			if (cntx[x] == 1)
				s1.erase(x);
			if (cnty[y] == 1)
				s2.erase(y);
		}
		else if (t == 2) {
			scanf("%d %d", &x, &y);
			cntx[x]--;
			cnty[y]--;
			if (cntx[x] == 0)
				s1.insert(x);
			if (cnty[y] == 0)
				s2.insert(y);
		}
		else if (t == 3) {
			int x1, y1, x2, y2;
			scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
			int xx = *s1.lower_bound(x1);
			int yy = *s2.lower_bound(y1);
			if (xx > x2 || yy > y2) {
				printf("YES\n");
			}
			else printf("NO\n");
		}
	}
}
int main() {
	std::cin.tie(nullptr);
	int t = 1;
	//cin>>t;
	while (t--) {
		solve();
	}

}

二.树状数组

#include<bits/stdc++.h>
using namespace std;
int n, q;
int row[100001];
int col[100001];
int x[100001];
int y[100001];
int lowbit(int x) {
	return x & (-x);
}
void add(int u, int x, int tree[]) {
	for (int i = u; i <= n; i += lowbit(i)) {
		tree[i] += x;
	}
}
int sum(int u, int tree[]) {
	int res = 0;
	for (int i = u; i >= 1; i -= lowbit(i)) {
		res += tree[i];
	}
	return res;
}
int main() {
	cin >> n >> q;
	while (q--) {
		int t;
		scanf("%d", &t);
		int x1, y1, x2, y2;
		scanf("%d %d", &x1, &y1);
		if (t == 1) {
			if (x[x1] == 0) add(x1, 1, row);
			if (y[y1] == 0) add(y1, 1, col);
			x[x1]++;
			y[y1]++;
		}
		if (t == 2) {
			if (x[x1] == 1) add(x1, -1, row);
			if (y[y1] == 1) add(y1, -1, col);
			x[x1]--;
			y[y1]--;

		}
		else if (t == 3) {
			scanf("%d %d", &x2, &y2);
			if (sum(x2, row) - sum(x1 - 1, row) == x2 - x1 + 1 || sum(y2, col) - sum(y1 - 1, col) == y2 - y1 + 1) printf("YES\n");
			else printf("NO\n");
		}
	}


}

三.线段树

#include<bits/stdc++.h>
using namespace std;
int n, q;
struct st {
	int l;
	int r;
	int sum;
}tr1[100001 * 4], tr2[100001 * 4];
int x[100001];
int y[100001];
void build(int u, int l, int r) {
	tr1[u] = { l,r,0 };
	tr2[u] = { l,r,0 };
	if (l == r) {
		tr1[u].sum = 0;
		tr2[u].sum = 0;
		return;
	}
	int mid = l + r >> 1;
	build(u << 1, l, mid);
	build(u << 1 | 1, mid + 1, r);
	tr1[u].sum = tr1[u << 1].sum + tr1[u << 1 | 1].sum;
	tr2[u].sum = tr2[u << 1].sum + tr2[u << 1 | 1].sum;
}
void update(int u, int l, int r, int k, st tree[]) {
	if (tree[u].l >= l && tree[u].r <= r) {
		tree[u].sum = k;
		return;
	}
	int mid = tree[u].l + tree[u].r >> 1;
	if (l <= mid) update(u << 1, l, r, k, tree);
	if (r > mid) update(u << 1 | 1, l, r, k, tree);
	tree[u].sum = tree[u << 1].sum + tree[u << 1 | 1].sum;
}
int query(int u, int l, int r, st tree[]) {
	if (tree[u].l >= l && tree[u].r <= r) return tree[u].sum;
	int res = 0;
	int mid = tree[u].l + tree[u].r >> 1;
	if (l <= mid) res += query(u << 1, l, r, tree);
	if (r > mid) res += query(u << 1 | 1, l, r, tree);
	return res;
}
int main() {
	cin >> n >> q;
	build(1, 1, n);
	while (q--) {
		int t;
		scanf("%d", &t);
		int x1, y1, x2, y2;
		scanf("%d %d", &x1, &y1);
		if (t == 1) {
			if (x[x1] == 0) update(1, x1, x1, 1, tr1);
			if (y[y1] == 0) update(1, y1, y1, 1, tr2);
			x[x1]++;
			y[y1]++;
		}
		if (t == 2) {
			if (x[x1] == 1) update(1, x1, x1, -1, tr1);
			if (y[y1] == 1) update(1, y1, y1, -1, tr2);
			x[x1]--;
			y[y1]--;

		}
		else if (t == 3) {
			scanf("%d %d", &x2, &y2);
			if (query(1, x1, x2, tr1) == x2 - x1 + 1 || query(1, y1, y2, tr2) == y2 - y1 + 1) printf("YES\n");
			else printf("NO\n");
		}
	}


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值