Educational Codeforces Round 160 (Rated for Div. 2)

A. Rating Increase

#include
#define endl '\n'
#define int long long
using namespace std;
string s;
void solve() {
	cin>>s;
	for(int i=0;i<(int)s.size()-1;i++){//枚举第一个字符串的右端点
		string s1,s2;
		for(int j=0;j<=i;j++) s1+=s[j];
		for(int j=i+1;j<(int)s.size();j++) s2+=s[j];
		if(s1[0]=='0'||s2[0]=='0') continue;
		int x=0,y=0;
		for(int j=0;j<(int)s1.size();j++) x=x*10+s1[j]-'0';
		for(int j=0;j<(int)s2.size();j++) y=y*10+s2[j]-'0';
		if(x<y){
			cout<<x<<' '<<y<<endl;
			return;
		}
	}
	cout<<-1<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

B. Swap and Delete
给定一个01串s
操作:删除一个字符,花费1金币或者免费交换一对字符
次数不限

使得ti不等于si对于整个t(可以为空)
问最少花费多少金币

两个一样的序列进行0和1的匹配,分别统计0和1的数量,从头开始遍历,一直到不能匹配

trick:

1.两两可以任意交换–可以随便排序

2.两两匹配问题

分为三种

第一种是序列内部进行两两匹配,比如说最小和最大匹配,次小和次大匹配

第二种是两个不同的序列进行匹配,比如说每次匹配差值最大的,要么序列a的最大和序列b的最小匹配,要么序列a的最小和序列b的最大匹配

第三种是两个一样的序列进行匹配,一般是通过自身元素的两两交换来满足某个要求,本质上就是自身和自身匹配

#include
#define endl '\n'
#define int long long
using namespace std;
string s;
void solve() {
	cin>>s;
	int n=s.size();
	map<char,int>mp;
	for(int i=0;i<n;i++) mp[s[i]]++;
	for(int i=0;i<(int)s.size();i++){
		if(s[i]=='1'){
			if(mp['0']) mp['0']--;
			else{
				cout<<n-i<<endl;
				return;
			}
		}
		else{
			if(mp['1']) mp['1']--;
			else{
				cout<<n-i<<endl;
				return;
			}
		}
	}
	cout<<0<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

C. Game with Multiset
add x表示在集合中添加一个2的x次方
get w问是否可以从集合中取得一些数,和为w

trick:
任何一个数都可以由若干个2的次幂组成

有两种方法:

1.将该数转化成二进制,然后一位一位看,如果第x位为1的话,那么 就有 2 x 2^x 2x,具体操作方法可以参考快速幂

while(x){
    if(x&1) ans.push_back(x); 
    x>>=1;
}

2.从高到低贪心

for(int i=29;i>=0;i--){
    if(x>=(1ll<<i)){
        ans.push_back(x);
        x-=(1ll<<i);
    }
}

但是你会发现,每一位二进制数都只用一次,该题中每个2的次幂不止一个,实际上从大到小贪心和每个2的次幂只用一次的贪心本质上是一样的

如果某个2的次幂有多个的话,那么就只保留一个(有奇数个)或者 一个也不保留(有偶数个),然后其余的进行合成,往上进位

比如说有5个 2 3 2^3 23,想当于1个 2 5 2^5 25

再比如说6个 2 3 2^3 23,相当于1个 2 5 2^5 25以及1个 2 4 2^4 24

所以总能转化成每个2的次幂只用一次

所以从高到低进行贪心,如果能构成就能,不能就不能

#include
#define endl '\n'
#define int long long
using namespace std;
int m;
void solve() {
	cin>>m;
	map<int,int>mp;
	while(m--){
		int op,x;
		cin>>op>>x;
		if(op==1) mp[x]++;
		else{
			for(int i=29;i>=0;i--){
				if(mp[i]){
					x-=min(x/(1ll<<i),mp[i])*(1ll<<i);
				}
			}
			if(x==0) cout<<"YES"<<endl;
			else cout<<"NO"<<endl;
		}
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
//    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

你可能感兴趣的:(codeforces,算法,c++)