Codeforces Round 960(Div.2)

Codeforces Round 960(Div.2)

A

  • 从大到小去判断数字个数的奇偶性,只要出现过奇数,先手必赢,如果不出现奇数,后手必赢
#include<iostream>
#include<queue>
#include<map>
#include<set>
using namespace std;

const int N = 55;
int a[N];

void solve() {
	int n;
	cin >> n;
	map<int,int>mp;
	set<int,greater<int> >s;
	set<int,greater<int> >::iterator iter;
	
	int sum = 0;
	//要么从小,要么就只考虑最大 

	for (int i = 1;i <= n;i++) {
		cin >> a[i];
		if(a[i] > sum) {
			sum = a[i];
		}
		mp[a[i]]++;
		s.insert(a[i]);
	}
	
	int cnt = 0;
	int ptr = 0;
	for(iter = s.begin();iter!=s.end();iter++) {
		if(mp[*iter] % 2) {
			ptr = 1;
			break;
		}
	}
	if(ptr) {
		cout<<"YES"<<endl;
	}else{
		cout<<"NO"<<endl;
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t;
	cin >> t;

	while (t--) {
		solve();
	}

	return 0;
}

B

  • 通过x , y来判定其分布,注意不能在边缘处全部放-1,要-1,1交替放置
#include<iostream>
#include<cstring>
using namespace std;

const int N = 1e5 + 10;
int a[N];
bool str[N];

void solve() {
	int n, x, y;//构造数组a使得其最大前缀位置是x
	//最大后缀位置是y
	cin >> n >> x >> y;

	memset(a, 0, sizeof a);
	memset(str,false,sizeof str); 
	
	int t = 1;
	for (int i = x + 1;i <= n; i++) {
		if(t==1)
		{
			a[i] = -1;
		}else{
			a[i] = 1;
		}	
		t = -t;
		str[i] = true;
	}
	
	t = 1;
	for (int i = y - 1;i >= 1;i--) {
		if(t==1)
		{
			a[i] = -1;
		}else{
			a[i] = 1;
		}	
		t = -t;
		str[i] = true;
	}
	
	for (int i = 1;i <= n;i++) {
		if (!str[i]) {
			a[i] = 1;
			str[i] = true;
		}
	}

	for (int i = 1;i <= n;i++) {
		cout << a[i] << " ";
	}
	cout << endl;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t;
	cin >> t;

	while (t--) {
		solve();
	}

	return 0;
}

C

  • 这个题第一次看错了题目,其MADMAD (Maximum Appearing Duplicate)别人的定义是1到i中出现两次即以上的最大数字,错以为成出现次数最多的数字
  • 先说结论:完成两次操作后,我们一定可以得到一个non—decreasing array,此后每一次操作我们都是将这个array往后移动一位,前面自己补充0
  • 1:第一次operation后,利用逆推思想,不难想象到我们可以形成这样一个片段

  • 2:即我们从后往前生成,$ x_n $ 是最大的出现两次数,而且是从这个数字的出现的第二个位置开始(不难发现所有数字都是这样)这里指的是\(x_n\)区域的形成,之后的区域以此类推
  • 3:之后又有一个问题就是first operation的数列怎么处理1,1,2,2,3,4,5,如果按照结论,我们应该期望得到的数组是0,1,1,2,2,3,4,但实际是0,1,1,2,2,2,2。这就是我们为什么要进行second operation
  • 4:不难发现,虽然目前数组已经是单增的了,但是有些元素是单个的,我们在second operation后,我们得到的数组一定是所有元素至少出现两次的,之后的右移也理所当然了。
#include<iostream>
#include<cstring>
#define int long long 
using namespace std;

const int N = 2e5 + 10;
int a[N];
int cnt[N];
int sum;
int n;

void solve() {
	memset(cnt,0,sizeof cnt);
	int maxn = 0;
	
	for(int i=1;i<=n;i++) {
		sum += a[i];
	}
	
	for(int i = 1;i <= n;i++) {
		cnt[a[i]]++;
		if(cnt[a[i]] >= 2 && a[i] >= maxn) maxn = a[i];
		a[i] = maxn;
	}
}

void solve_plus() {
	for(int i=1;i<=n;i++) {
	 	if(a[i]) {
	 		sum += a[i] * (n - i + 1);
		}
	}
	
	cout<<sum<<endl;
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	
	int t;
	cin>>t;	
	
	while(t--) {
		
		cin>>n;
		
		sum = 0;
		
		for(int i=1;i<=n;i++) {
			cin>>a[i];
		}
		solve();
		solve();
		solve_plus();
	}
	
	return 0; 
}
posted @ 2024-07-21 15:21  Mikkeykarl  阅读(46)  评论(0)    收藏  举报