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;
}

浙公网安备 33010602011771号