Codeforces Round #823 (Div. 2) A-C题解

比赛链接

A、Planets

水题。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 10010
#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, c; 
int a[N]; 
int tong[N]; 
vector <int> G; 

int main(){
  // freopen("hh.txt", "r", stdin); 
  int T; read(T);
  while(T--){
    G.clear(); 
    memset(tong, 0, sizeof(tong)); 
    read(n), read(c);
    for(int i = 1; i <= n; i++)
      read(a[i]); 
    for(int i = 1; i <= n; i++){
      if(!tong[a[i]]) G.push_back(a[i]); 
      tong[a[i]]++; 
    }
    int ans = 0; 
    for(int i = 0; i < G.size(); i++){  // 对于每一个轨道,看有多少个星球
      if(tong[G[i]] > c) ans += c;
      else ans += tong[G[i]]; 
    }
    cout << ans << endl; 
  }
  return 0;
}

B、Meeting on the Line

十分少见的 B 比 C 难。
两种思路。
第一种,用二分法不断逼近最短时间,并通过时间判断出每个人的可行域。之后得到一总线段交,即为该时间下可以选择的位置区间。受限于精度,当区间足够小时,便可以直接输出区间内任一位置。

第二种,考虑等效转化。如果没有换装时间这个限制,显然我们选择最大和最小值二者的中点即可。但是加上时间限制后,我们考虑将换装时间转化为距离。
可以发现,对于给定的 \(x_0\), 一个人到此处的时间就是其坐标向远端挪时间 \(t_i\) 个单位。因此,可以将一个人拆成两个点。

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

int main(){
  freopen("hh.txt", "r", stdin); 
  int T; read(T);
  while(T--){
    int n; read(n);
    for(int i = 1; i <= n; i++){
      read(a[i]); 
    }
    for(int i = 1; i <= n; i++)
      read(t[i]);
    set<double> s; 
    for(int i = 1; i <= n; i++){
      s.insert(a[i] - t[i]);
      s.insert(a[i] + t[i]); 
    }
    double dis = 0.0; 
    double minn = *s.begin();
    set<double>::iterator it = s.end();  it--; 
    double maxn = *it;
    printf("%.8lf\n", (maxn + minn) / 2.0); 
  }
  return 0;
}

C、Minimum Notation

可以发现,保留当前后缀中的最小数字肯定是最优的。因此,要把最小数字之前的数字全部删掉提到后面来,使其尽量靠前。最后排序输出即可。

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

int main(){
  // freopen("hh.txt", "r", stdin); 
  int T; read(T);
  while(T--){
    scanf("%s", s1 + 1);
    int n = strlen(s1 + 1);
    for(int i = 1; i <= n; i++)
      a[i] = s1[i] - '0', minn[i] = 1e9;
    minn[n+1] = 1e9;
    for(int i = n; i; i--){
      minn[i] = min(minn[i+1], a[i]); 
    }

    multiset <int> s; 
    for(int i = 1; i <= n; i++){
      if(a[i] > minn[i])s.insert(min(a[i]+1, 9)); 
      else s.insert(a[i]); 
    }
    for(auto it : s){
      printf("%d", it); 
    }
    cout << endl; 
  }
  return 0;
}

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