Codeforces Round 960 (Div. 2)

题目链接

点击跳转codeforces

A. Submission Bait

 这是一道博弈题,比较简单,但是赛时直接就WA了两发,刚开始把题想简单了,第二发没有考虑清楚。
 题意:一串数字,Alice如果选了6,那么Bob必须选择大于等于6的数,然后Alice再选择大于等于Bob的数字,如此以往,谁选不到谁就输了
 思路:将每个数字出现的次数统计起来,从大到小遍历每个数字出现的次数,如果有一个是奇数的话,Alice就赢,否则就Bob赢。
因为假如是5,5,5,5,5,4,3,1,4,2的排列的话,我Alice直接选最大的5,那Bob就只能选5,选到最后一定是Bob输,我们用一个map数组,然后从后往前遍历,出现奇数个的就输出YES,否则到最后再输出NO

#include <bits/stdc++.h>
#define int long long 
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define fi first
#define se second
#define PII pair <int,int>
#define ALL(x) x.begin(),x.end()
#define lowbit(x) (x&(-x))
using namespace std;
const int N = 1e6+5;
int mp[N];
int a[N];
void solve () {
	memset(mp,0,sizeof(mp));
	int n;cin>>n;
	for (int i=1;i<=n;i++) {
		cin>>a[i];mp[a[i]]++;
	}
	for (int i=50;i>=1;i--) {
		if (mp[i]) {
			if (mp[i]&1) {
				cout<<"YES"<<'\n';return ;
			}
		}
	}
	cout<<"NO"<<'\n';
	
}

signed main () {
	IOS;
	int T =1;
	cin>>T;
	while(T--) solve ();
	return 0;
}

B. Array Craft

这是一道构造题,让构造出一个数组满足以上的条件:

  • 最大前缀的最小位置在x
  • 最大后缀的最大位置在y
  • 数组都是1或者-1
    我一开始的思想是将x,y里面的数字全部变成1,以外的数字都是-1.但是赛时我发现了,这样就不满足前两个条件了如果是-1,-1,-1,-1,-1,1,1,1,-1,-1,-1,-1这样的数组,从前加到最后一个1值是-2,但是从前往后加为-2的地方的最小的位置是第二个-1的位置,所以我们要构造前面加起来大于-2的值,那为什么是-2呢,因为x,y之间的和最小就是2,而且在y-1和x+1的位置都要是-1,然后再往两边构造,-1,1交替出现
#include <bits/stdc++.h>
#define int long long 
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define fi first
#define se second
#define PII pair <int,int>
#define ALL(x) x.begin(),x.end()
#define lowbit(x) (x&(-x))
using namespace std;
const int N = 1e5+5;
int a[N],b[N];

void solve () {
//如果在这里对a,b数组初始化的话,会降低效率,容易超时,我就超了一次
	int n,y,x;cin>>n>>y>>x;
	int k=0;
	for (int i=x-1;i>=1;i--) {
		if (k%2==0)
		a[++k]=-1;
		else a[++k]=1;
	}
	for (int i=k;i>=1;i--) cout<<a[i]<<' ';
	for (int i=x;i<=y;i++) cout<<"1"<<' ';
	k=0;
	for (int i=y+1;i<=n;i++) {
		if (k%2==0)
		b[++k]=-1;
		else b[++k]=1;
	}
	for (int i=1;i<=k;i++) cout<<b[i]<<' ';
}

signed main () {
	IOS;
	int T =1;
	cin>>T;
	while(T--) solve ();
	return 0;
}

C. Mad MAD Sum

在这里插入图片描述
 一道难度不小的思维题我认为,数组在经过第一次变化之后会变成一个非递减序列,我们将样例多变化几次就可以发现似乎是在每次向右移动一位一样,例如:1,2,3,4,5,5,6,7,7,9,6,5,9,9会变化成0,0,0,0,0,5,5,5,7,7,7,7,9,9,然后变化成0,0,0,0,0,0,5,5,5,7,7,7,7,9,然后变成0,0,0,0,0,0,0,5,5,5,7,7,7,7可以看出来向右移动一位。但是不都是这样的,例如2,1,1,2,2,2变成0,0,1,2,2,2,变成0,0,0,0,2,2就不是单纯向右移动一位了,只有一个一样的就是会出现这种情况,我们只需要将原数组操作两次就可以往右一直移动求和了。

#include <bits/stdc++.h>
#define int long long 
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define fi first
#define se second
#define PII pair <int,int>
#define ALL(x) x.begin(),x.end()
#define lowbit(x) (x&(-x))
using namespace std;
const int N = 1e6+5;
int a[N],b[N];

void solve () {
	int n;cin>>n;int sum=0;
	for (int i=1;i<=n;i++) {
		cin>>a[i];sum+=a[i];
	}	
	if (n==1) {
		cout<<sum<<'\n';return ;
	}
	int f=1;int flag=1;int cnt=0;int pos=0;
	map<int,int>mp;int my=0;
	for (int i=1;i<=n;i++) {
		mp[a[i]]++;
		if(mp[a[i]]>=2) {
			if (a[i]>my) my=a[i];
		}		
		a[i]=my;sum+=my;
	}
	map<int,int>mp1;my=0;
	for (int i=1;i<=n;i++) {
		mp1[a[i]]++;
		if(mp1[a[i]]>=2) {
			if (a[i]>my) my=a[i];
		}		
		if (my==0) cnt++;	
		a[i]=my;pos+=my;
	}
	int t=n-cnt;
	for (int i=1;i<=t;i++) {
		sum+=pos;
		pos-=a[n-i+1];
	}
	cout<<sum<<'\n';
}

signed main () {
	IOS;
	int T =1;
	cin>>T;
	while(T--) solve ();
	return 0;
}
  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值