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

posted @ 2022-10-25 21:28  雪之下,树之旁  阅读(25)  评论(0编辑  收藏  举报