Educational Codeforces Round 138 (Rated for Div. 2)题解 (A-C)

比赛链接

A.Cowardly Rooks

dfs暴搜即可。

点击查看代码
#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, m; 
int fx[5] = {0, 1, -1, 0, 0};
int fy[5] = {0, 0, 0, 1, -1}; 
int x[N], y[N]; 
int a[10][10]; 

bool flag = 0; 

bool check(){
  for(int i = 1; i <= m; i++){
    for(int j = i + 1; j <= m; j++){
      if(x[i] == x[j] || y[i] == y[j]) return 0; 
    }
  }
  return 1; 
}

bool vis[10][10]; 

void dfs(int nx, int ny, int now, int id){
  if(flag) return ; 
  if(now > n * n) return ; 
  if(now > 1){
    if(check()){
      flag = 1;
      return ; 
    }
    // return ; 
  }
  vis[nx][ny] = 1; 
  for(int i = 1; i <= 4; i++){
    int dx = nx + fx[i];
    int dy = ny + fy[i]; 
    if(dx < 1 || dy < 1 || dx > n || dy > n || a[dx][dy] || vis[dx][dy]) continue ; 
    x[id] = dx, y[id] = dy; 
    dfs(dx, dy, now + 1, id); 
    x[id] -= fx[i]; y[id] -= fy[i]; 
  }
  return ; 
}

int main(){
  // freopen("hh.txt", "r", stdin); 
  int T; read(T);
  while(T--){
    memset(vis, 0, sizeof(vis)); 
    memset(a, 0, sizeof(a)); 
    read(n), read(m);
    for(int i = 1; i <= m; i++){
      read(x[i]), read(y[i]); 
      a[x[i]][y[i]] = 1; 
    }
    flag = 0; 
    for(int i = 1; i <= m; i++){
      dfs(x[i], y[i], 1, i); 
      if(flag) break; 
    }
    if(flag) puts("YES");
    else puts("NO"); 
  }
  return 0;
}

B. Death's Blessing

首先,对于数组 \(a\), 我们是躲不掉的。因此直接把 \(a\) 全部加上先,然后不管他了。
然后,发现,当 \(b\) 中一个数处于数组两端时,只会有一个贡献。处于中间则会有两倍贡献。
再想想,\(b\) 中的所有数也是不可避免的,除了最后一个。因此,保留最大的那个数到最后一个删,剩下的数都留到两侧删即可。

点击查看代码
#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 a[N], b[N]; 
ll ans = 0; 

struct point{
  int id;
  int w; 
} ; 

priority_queue <int, vector<int>, greater<int> > q; 
map <int, int> g; 

int main(){
  // freopen("hh.txt", "r", stdin); 
  int T; read(T);
  while(T--){
    while(!q.empty()) q.pop(); 
    ans = 0; 
    int n; read(n);
    for(int i = 1; i <= n; i++){
      read(a[i]); 
    }
    for(int i = 1; i <= n; i++){
      read(b[i]); 
    }
    for(int i = 1; i <= n; i++) ans += a[i];
    int l = 1, r = n;   // 目前最靠边的两个 boss
    while(l < r){
      if(b[l] < b[r]){
        ans += b[l];
        l++; 
      }
      else{
        ans += b[r];
        r--; 
      }
    }
    cout << ans << endl; 
  }
  return 0;
}

C. Number Game

先推个柿子 \(a + k - i + 1 \ge k - (i + 1) + 1 -> a > -1\)
所以,对于 \(Bob\), 他选择任何一个数都可以让其变为非法。
对于 \(Alice\), 发现她会优先选最大的删,因为 \(k - i + 1\) 会不断缩小。这时,如果 \(Bob\) 选择小的数字,就可以断 \(Alice\) 后路,从两侧缩小 \(Alice\) 的区间。选大数显然不优。

点击查看代码
#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; 
int a[N]; 
priority_queue <int> q; 

int main(){
  // freopen("hh.txt", "r", stdin); 
  int T; read(T);
  while(T--){
    read(n); 
    for(int i = 1; i <= n; i++) read(a[i]);
    int ans = 0; 

    sort(a + 1, a + n + 1); 
    for(int k = n; k >= 0; k--){
      
      bool flag = 1; 
      int l = 1, r = n; 
      for(int i = 1; i <= k; i++){
        while(a[r] > k - i + 1 && r >= 1) r--;    
        if(r < l){
          flag = 0;
          break; 
        }
        r--;
        l++;
      }
      if(flag){
        ans = k;
        break; 
      }
    }
    cout << ans << endl; 
  }
  return 0;
}

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