Codeforces Round 817 (Div. 4)E~G

Codeforces Round 817 (Div. 4)E~G

E. Counting Rectangles(前缀和)

题意

给n个矩形,每个矩形高hi,宽wi

然后q次询问,给hs,ws,hb,wb。然后输出所有hs<hi<hb&&ws<wi<wb的矩形面积的和

思路

二维前缀和数组sum[i][j],表示所有h<=hi&&w<=wi的矩形面积和

然后询问的时候直接输出区间前缀和就行

sumS[i][j] = sumS[i - 1][j] + sumS[i][j - 1] - sumS[i - 1][j - 1] + s[i][j]

代码

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
vector<long long>ans;

void solve() {
	int n, q; cin >> n >> q;
	int hs, ws, hb, wb;

	vector<vector<long long>>s(1005, vector<long long>(1005));
	vector<vector<long long>>sumS(1005, vector<long long>(1005));
	for (int i = 1, h, w; i <= n; i++) {
		cin >> h >> w;
		s[h][w] += h * w;
	}
	for (int i = 1; i <= 1000; i++) {
		for (int j = 1; j <= 1000; j++) {
			sumS[i][j] = sumS[i - 1][j] + sumS[i][j - 1] - sumS[i - 1][j - 1] + s[i][j];
		}
	}

	while (q--) {
		cin >> hs >> ws >> hb >> wb;
		long long res = sumS[hb - 1][wb - 1]  - sumS[hb-1][ws] - sumS[hs][wb-1] + sumS[hs][ws];
		cout << res << endl;
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int _; _ = 1;
	cin >> _;
	while (_--)	solve();
	for (auto x : ans)cout << x << endl;
	return 0;
}
// 二维前缀和

F. L-shapes(DFS)

题意

给一个矩形网格,里面的矩形只能组成L形,也不能落单什么的,而且L之间不能相邻,或者某个矩形的对角有矩形

思路

其实意思就是,在组成了L的这三个矩形,每个矩形的八个方向,不能有除了自己L的矩形外的其他矩形

然后另一个就是判断是不是所有矩形都组成了L(否则就不合法)

从头到尾遍历二维网格,遇到一个矩形就尝试DFS整个L。当然由于我们这种遇到一个矩形就深搜的方式,所以我们的L只能是

** ** * *

* * ** **

这四种

DFS的过程就是,首先看当前矩形是否形成L,然后再看这个L的所有矩形周围是否有其他矩形

代码

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
vector<string>ans;
int n, m;
int dx[] = { -1,-1,-1,0,1,1,1,0 };
int dy[] = { -1,0,1,1,1,0,-1,-1 };
int dx3[] = { 0,1,1 };
int dy3[] = { 1,1,0 };
char mp[55][55];
int vis[55][55];

bool check(int x, int y) {
	// 此时处于最后一行,必定没有L了
	if (x + 1 > n )return false;

	// 尝试作为左上角/右上角
	vector<int>vx = { x }, vy = { y };
	int cnt = 1;
	if (y + 1 <= m) {
		for (int i = 0; i < 3; i++) {
			int nx = x + dx3[i];
			int ny = y + dy3[i];
			if (vis[nx][ny])return false;
			if (mp[nx][ny] == '*') {
				cnt++;
				vx.push_back(nx);
				vy.push_back(ny);
			}
		}
	}
	// 作为左上角失败了,尝试作为右上角
	if (cnt != 3) {
		if (mp[x + 1][y - 1] == '*' && mp[x + 1][y] == '*') {
			cnt = 3;
			vx = { x,x + 1,x + 1 };
			vy = { y,y - 1,y };
		}
	}

	if (cnt != 3)return false;

	for (int i = 0; i < 3; i++) {
		int curX = vx[i];
		int curY = vy[i];
		for (int j = 0; j < 8; j++) {
			int nx = curX + dx[j];
			int ny = curY + dy[j];
			if (0 >= nx || 0 >= ny || nx > n || ny > m || mp[nx][ny] == '.')continue;
			if (vis[nx][ny])return false;
		}
	}
	for (int i = 0; i < 3; i++) {
		vis[vx[i]][vy[i]] = 1;
	}
	return true;
}

void solve() {
	// 八向搜,看有没有除了三个点以外的其他点
	cin >> n >> m;
	memset(mp, 0, sizeof(mp));
	memset(vis, 0, sizeof(vis));
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> mp[i][j];
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (vis[i][j] || mp[i][j] != '*')continue;
			if (!check(i, j)) {
				//cout << "i:" << i << "j:" << j << endl;
				//cout << "NO" << endl;
				ans.push_back("NO");
				return;
			}
		}
	}
	//cout << "YES" << endl;
	ans.push_back("YES");
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int _; _ = 1;
	cin >> _;
	while (_--)	solve();
	for (auto x : ans)cout << x << endl;
	return 0;
}

G. Even-Odd XOR(数学,位运算)

题意

构造一个长度为n,全部奇数下标的异或值等于全部偶数下标的异或值

思路

也就是所有数的异或结果为0

构造的方法是

前面n-3个数,就从1开始,一直递增就行。1,2,3,4……

然后到了an-2就设置乘1<<23

an-1设置为1<<24

这个23,24是只要比n的最高位高就行

最后an就设置为了最高两位是1,为了最终异或结果的时候,这两位也是为0

那么低位,就是a1一直异或到an-3的结果,这样也可以使得低位结果为0

代码

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;

void solve() {
	int n; cin >> n;
	int res = 0;
	for (int i = 1; i <= n - 3; i++) {
		cout << i << " ";
		res ^= i;
	}
	cout << (1 << 23) << " " << (1 << 24) << " ";
	cout << (res ^ (1 << 23) ^ (1 << 24)) << endl;
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int _; _ = 1;
	cin >> _;
	while (_--)	solve();
	return 0;
}
posted @ 2025-04-30 12:55  zombieee  阅读(19)  评论(0)    收藏  举报