Codeforces Round #823 (Div. 2) 补题题解 (A、B、C)

Source


A Planets (800)

简单模拟,看见这个数据范围就是放手模拟

#include<bits/stdc++.h>

using namespace std;

const int N = 110;

int T;
int c, n, a[N];
map<int, int>mp;
int p[N];

void solve(){
    
      
	cin>>n>>c;
	int ans = n;
	int res = 0;
	mp.clear();
	
	for(int i = 1; i <= n; i ++ ){
    
      
		cin>>a[i];
		if(!mp[a[i]]){
    
        //如果这个数没有出现过 
			p[ ++ res] = a[i];
		}
		mp[a[i]] ++ ;
	}
	
	for(int i = 1; i <= res; i ++ ){
    
      
		if(mp[p[i]] >= c){
    
      
			ans -= mp[p[i]];
			ans += c;
		}
	}
	
	cout<<ans<<endl;
}

int main()
{
    
      
	cin>>T;
	while(T -- ){
    
      
		solve();
	}
	return 0;
}

B Meeting on the Line (1600)

这题是真不容易,看了好几份题解终于明白二分的是什么东西和过程
二分:找到合适的时间T(mid),所有人到达的时间都要小于等于mid,让mid尽可能的小,就是二分最终的目的

请添加图片描述

#include<bits/stdc++.h>

using namespace std;

#define db double

const int N = 2e5 + 10;

int T;
int n, a[N];
int t[N];
db ans;

bool check(db mid){
    
      
	db l = -1e9, r = 1e9;
	for(int i = 1; i <= n; i ++ ){
    
      
		if(mid <= t[i]) return false;
		else{
    
      
			l = max(l, t[i] + a[i] - mid);  //l是所有时间的下限的最大值,就是说合适的x0至少要大于这个数 
			r = min(r, -t[i] + a[i] + mid);
		}
	}
	ans = l;
	return r + (1e-8) >= l;
}

void solve(){
    
      
	cin>>n;
	for(int i = 1; i <= n; i ++ ) cin>>a[i];
	for(int i = 1; i <= n; i ++ ) cin>>t[i];
	
	db l = 0, r = 2e18;
	for(int i = 1; i <= 100; i ++ ){
    
      
		db mid = (l + r) / 2;
		if(check(mid)) r = mid;  //如果这个时间可以,那么还可以缩小时间 
		else l = mid;
	}
	check(r);
	printf("%.10lf\n", fabs(ans));
}

int main()
{
    
      
	cin>>T;
	while(T -- ){
    
      
		solve();
	}
	return 0;
}

C Minimum Notation (1200)

不看题解第一次写出来1200的题吧,确实进步了
思维转换题,比较每个数字比他小的有没有在他后面的,如果有,这个数就应该变为min(x + 1, 9)往后方,用两个map,一个记录数量,一个记录位置即可

#include<bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

int T;
int c, n, a[N];
map<int, int>mp1, mp2;
int p[N];

void solve(){
    
      
	string str;
	cin>>str;
//	str = "+" + str;
	mp1.clear();
	mp2.clear();
//	cout<<str<<endl;
	for(int i = 0; i < str.size(); i ++ ){
    
      
		int t = (int)(str[i] - '0'); 
		mp1[t] = max(mp1[t], i);  //记录这个数出现的最后位置 
		mp2[t] ++ ;
	//	cout<<t<<"*";
	}
	
	for(int i = 0; i < str.size(); i ++ ){
    
      
		int t = (int)(str[i] - '0');
	//	cout<<t<<"*";
		for(int j = 0; j < t; j ++ ){
    
      
		//	cout<<t<<"***"<<endl;
			if(mp1[j] > i){
    
      
				mp2[t] -- ;
				mp2[min(9, t + 1)] ++ ;
				//cout<<"***"<<endl; 
				break; 
			}
		}
	}
	
	for(int i = 0; i <= 9; i ++ ){
    
      
		for(int j = 0; j < mp2[i]; j ++ ){
    
      
			cout<<i;
		}
	}
	cout<<endl;
}

int main()
{
    
      
	cin>>T;
	while(T -- ){
    
      
		solve();
	}
	return 0;
}

自己解决了1200的题,又明白了一个1600的二分题,感觉这个思路很有价值,后面2200的题实在补不动了,下一场见,有进步,继续冲!