Codeforces Round 915 (Div. 2)

A. Constructive Problems

#include
#define endl '\n'
#define int long long
using namespace std;
int n,m;
void solve() {
	cin>>n>>m;
	cout<<max(n,m)<<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. Begginer’s Zelda

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=1e5+10;
int d[N];
int n;
void solve() {
	cin>>n;
	memset(d,0,sizeof d);
	for(int i=0;i<n-1;i++){
		int u,v;
		cin>>u>>v;
		d[u]++;
		d[v]++;
	}
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(d[i]==1) cnt++;
	}
//	cout<
	int ans=(cnt-2)/2+((cnt-2)%2!=0)+1;
	cout<<ans<<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. Largest Subsequence
长度为n的字符串
操作:得到字典序最大的子序列,并循环右移一位
问最少几次可以排好序,无解输出-1

从大到小贪心选取后面出现的最大的(利用后缀最大值,当等于后缀最大值时就选取)
那么这个序列就是非升序的,每次循环右移就是把最小的一位放到最前面,那么最少的次数就是把这个序列排成非降序,用整个序列的个数减去最大的那个的个数即可,因为如果最大的不止一个,那么不需要再移了
最后,把排好序的序列放回原来的位置,进行检验

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=2e5+10;
int last[N];
int n;
string s;
void solve() {
	cin>>n>>s;
	memset(last,0,sizeof last);
	bool ok=true;
	for(int i=1;i<n;i++){
		if(s[i]<s[i-1]){
			ok=false;
			break;
		}
	}
	if(ok){
		cout<<0<<endl;
		return;
	}
	map<int,int>mp,mmp;
	last[n-1]=s[n-1]-'0';//后缀最大值
	for(int i=n-2;i>=0;i--) last[i]=max((int)(s[i]-'0'),last[i+1]);
	multiset<char>se;
	for(int i=0;i<n;i++){
		if(s[i]-'0'==last[i]){
			se.insert(s[i]);
			mp[i]++;
			mmp[s[i]-'0']++;
		}
	}
	char ch=*(--se.end());
	int ans=se.size()-mmp[ch-'0'];
	for(int i=0;i<n;i++){
		if(!mp[i]) continue;
		s[i]=*se.begin();
		se.erase(se.begin());
	}
	for(int i=1;i<n;i++){
		if(s[i]<s[i-1]){
			cout<<-1<<endl;
			return;
		}
	}
	cout<<ans<<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++)