Codeforces Round #817 (Div. 4) 题解
A、Spell Check
水题。不多说。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
int a[N];
int main(){
// freopen("hh.txt", "r", stdin);
int T; read(T);
while(T--){
memset(a, 0, sizeof(a));
int n; read(n);
string s; cin >> s;
if(n != 5) puts("NO");
else{
for(int i = 0; i < n; i++) a[s[i]]++;
if(a['T'] == 1 && a['i'] == 1 && a['m'] == 1 && a['u'] == 1 && a['r'] == 1)
puts("YES");
else puts("NO");
}
}
return 0;
}
B、Colourblindness
可以发现,蓝色和绿色等价。只有其中一行为红色且宁外一行不是红色时,可以分辨。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
int n;
char a[101];
char b[101];
int main(){
// freopen("hh.txt", "r", stdin);
int T; read(T);
while(T--){
read(n);
scanf("%s", a + 1);
scanf("%s", b + 1);
bool flag = 0;
for(int i = 1; i <= n; i++){
if((a[i] == 'R' && b[i] != 'R') || (a[i] != 'R' && b[i] == 'R')){
flag = 1;
break;
}
}
if(flag) puts("NO");
else puts("YES");
}
return 0;
}
C、Word Game
用STL暴力搞就好。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
map <string, vector<int> > G;
set <string> h;
int ans[4];
int main(){
// freopen("hh.txt", "r", stdin);
int T; read(T);
while(T--){
G.clear();
h.clear();
memset(ans, 0, sizeof(ans));
int n; read(n);
for(int j = 1; j <= 3; j++){
for(int i = 1; i <= n; i++){
string s; cin >> s;
G[s].push_back(j);
h.insert(s);
}
}
for(auto it1 : h){
if(G[it1].size() == 3) continue;
else if(G[it1].size() == 2){
for(auto it2 : G[it1]){
ans[it2] += 1;
}
}
else{
for(auto it2 : G[it1]){
ans[it2] += 3;
}
}
}
for(int i = 1; i <= 3; i++)
printf("%d ", ans[i]);
cout << endl;
}
return 0;
}
D、Line
考虑贪心。(比官方题解更快的 \(O(N)\) 解法)可以发现,在左半边的人,朝右看肯定更优。在右半边的人同理。因此,用双指针依次比较即可。左右两边选择更优的那一边即可。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
#define int long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
char t[N];
int s[N]; // 1: 向左 0: 向右
int a[N][2]; // 1: 左看 0: 右看
int ans[N];
signed main(){
// freopen("hh.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int T; read(T);
while(T--){
int n; read(n);
scanf("%s", t + 1);
for(int i = 1; i <= n; i++) s[i] = (t[i] == 'L');
int l = 1, r = n;
for(int i = 1; i <= n; i++){
a[i][1] = i - 1;
a[i][0] = n - i;
}
int nowk = 0;
ans[0] = 0;
for(int i = 1; i <= n; i++){
ans[0] += a[i][s[i]];
}
while(l <= r){
while(a[l][s[l]] >= a[l][s[l]^1] && l <= r) l++;
while(a[r][s[r]] >= a[r][s[r]^1] && r >= l) r--;
if(l > r) break;
if(a[l][s[l]^1] - a[l][s[l]] >= a[r][s[r]^1] - a[r][s[r]]){
nowk++;
ans[nowk] = ans[nowk-1] + a[l][s[l]^1] - a[l][s[l]];
l++;
}
else{
nowk++;
ans[nowk] = ans[nowk-1] + a[r][s[r]^1] - a[r][s[r]];
r--;
}
}
for(int i = 1; i <= nowk; i++)
cout << ans[i] << " ";
for(int i = nowk + 1; i <= n; i++)
cout << ans[nowk] << " ";
cout << endl;
}
return 0;
}
E、Counting Rectangles
水题。用二维前缀和即可。记得开 long long。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
int n, Q;
ll w[N], h[N];
ll sum[1001][1001];
int main(){
// freopen("hh.txt", "r", stdin);
int T; read(T);
while(T--){
read(n); read(Q);
memset(sum, 0, sizeof(sum));
for(int i = 1; i <= n; i++) read(h[i]), read(w[i]);
for(int i = 1; i <= n; i++){
sum[h[i]][w[i]] += h[i] * w[i];
}
for(int i = 1; i <= 1000; i++){
for(int j = 1; j <= 1000; j++){
sum[i][j] += sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1];
// printf("i: %d j: %d sum: %d\n", i, j, sum[i][j]);
}
}
while(Q--){
int h1, h2, w1, w2;
read(h1), read(w1), read(h2), read(w2);
h2--, w2--;
// printf("h2: %d w2: %d sum: %d\n", h2, w2, sum[h2][w2]);
printf("%lld\n", sum[h2][w2] - sum[h2][w1] - sum[h1][w2] + sum[h1][w1]);
}
}
return 0;
}
F、L-shapes
此处为比官方题解更优的做法。官方居然写了一坨循环暴力判断,实在没必要。
首先,考虑合法 \(L\) 形状,可以发现,合法 \(L\) 中所有格子的周边深色格子只能为 \(2\) 。因此利用这个性质扫一遍判断即可。但是,需要注意一种特殊情况,即三个格子在一条线上的情况。
点击查看代码
#pragma GCC optimize (2)
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
char d[1001][1001];
int n, m;
int fx[5] = {0, 0, 0, 1, -1};
int fy[5] = {0, 1, -1, 0, 0};
int fx1[10] = {0, 0, 0, 1, -1, 1, 1, -1, -1};
int fy1[10] = {0, 1, -1, 0, 0, 1, -1, 1, -1};
bool flag = 1;
bool check(pair<int, int> a, int x, int y, pair<int, int> b){
int nx = a.first, ny = a.second;
for(int i = 1; i <= 8; i++){
int dx = nx + fx1[i];
int dy = ny + fy1[i];
if(dx != x && dy != y && dx >= 1 && dy >= 1 && dx <= n && dy <= m && dx != b.first && dy != b.second){
if(d[dx][dy] == '*') return 0;
}
}
return 1;
}
bool check1(int nx, int ny, pair<int, int> a, pair<int, int> b){
for(int i = 1; i <= 8; i++){
int dx = nx + fx1[i];
int dy = ny + fy1[i];
if(dx < 1 || dx > n || dy < 1 || dy > m) continue;
if(dx == a.first && dy == a.second) continue;
if(dx == b.first && dy == b.second) continue;
if(d[dx][dy] == '*') return 0;
}
return 1;
}
vector <pair<int, int> > s;
int main(){
// freopen("hh.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int T; read(T);
while(T--){
memset(d, 0, sizeof(d));
flag = 1;
read(n), read(m);
for(int i = 1; i <= n; i++)
scanf("%s", d[i] + 1);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(d[i][j] != '*') continue;
int num = 0;
set <pair<int, int> > s;
for(int h = 1; h <= 8; h++){
int dx = i + fx1[h];
int dy = j + fy1[h];
if(dx < 1 || dx > n || dy < 1 || dy > m) continue;
if(d[dx][dy] == '*') num++, s.insert(make_pair(dx, dy));
}
if(num != 2){
flag = 0;
break;
}
auto it = s.begin();
pair<int, int> tmp1 = *it; it++;
pair<int, int> tmp2 = *it;
if(tmp1.first == i - 1 && tmp2.first == i + 1){
flag = 0;
break;
}
if(tmp1.second < tmp2.second) swap(tmp1, tmp2);
if(tmp1.second == j + 1 && tmp2.second == j - 1){
flag = 0;
break;
}
}
if(!flag) break;
}
if(flag) puts("Yes");
else puts("No");
}
return 0;
}
G、Even-Odd XOR
蒟蒻实在是太弱了。在想到奇偶交替后,被最后两位的处理卡住乐。。。。。其实,将前 \(n - 3\) 位按顺序输出,倒数第三和第二位取极大值 \(2^{29}\) 与 \(2^{30}\) ,最后一位输出前面 \(n - 1\) 位的和即可。(手摸一下就知道了)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define ll long long
template <class T>
inline void read(T& a){
T x = 0, s = 1;
char c = getchar();
while(!isdigit(c)){ if(c == '-') s = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); }
a = x * s;
return ;
}
int ans[N];
int main(){
// freopen("hh.txt", "r", stdin);
int T; read(T);
while(T--){
int n; read(n);
int num = 0;
for(int i = 1; i <= n - 3; i++){
ans[i] = i - 1;
num ^= ans[i];
}
ans[n-2] = (1 << 29);
ans[n-1] = (1 << 30);
num ^= ans[n-2];
num ^= ans[n-1];
ans[n] = num;
for(int i = 1; i <= n; i++)
printf("%d ", ans[i]);
cout << endl;
}
return 0;
}