Codeforces Round 888 (Div. 3) A~F

原题链接:Dashboard - Codeforces Round 888 (Div. 3) - Codeforces

目录

A. Escalator Conversations

 B. Parity Sort

 C. Tiles Comeback

D. Prefix Permutation Sums 

 E. Nastya and Potions

F. Lisa and the Martians


A. Escalator Conversations

题意: 

 思路:暴力枚举楼梯可以造成的所有差值,然后判断即可。注意楼梯造成的差值最小为k,最大为(m-1)*k。

代码:

void solve() {
	int n,m,k,h,ans=0;
	cin>>n>>m>>k>>h;
	for(int i=1; i<=n; i++) {
		int x;
		cin>>x;
		for(int j=1; j<m; j++) {
			if(x-j*k==h||x+j*k==h) {
				ans++;
				break;
			}
		}
	}
	cout<<ans<<endl;
}

 B. Parity Sort

题意:

思路:因为奇数元素的位置只能由奇数元素换过来,所以若能有序的话,排完序之后原本奇数位置上还是奇数,偶数位置上还是偶数。

代码:

void solve() {
	int n;
	cin>>n;
	for(int i=1; i<=n; i++) {
		cin>>a[i];
		b[i]=a[i];
	}
	sort(a+1,a+n+1);
	for(int i=1; i<=n; i++) {
		if(a[i]%2!=b[i]%2) {
			no;
			return;
		}
	}
	yes;
}

 C. Tiles Comeback

题意:

思路:只要有k个元素和第一个元素颜色相同,并且有k个元素和最后一个元素颜色相同 ,并且选择这两种颜色的区间不相交,答案即为YES。特别的是,第一个元素和最后一个元素颜色相同,此时只需要k个颜色即可。

代码:

void solve() {
	PII l,r;
	int n,k;
	cin>>n>>k;
	for(int i=1; i<=n; i++) {
		cin>>a[i];
		if(a[i]==a[1]&&l.second!=k)l.first=i,l.second++;
	}
	for(int i=n; i>=1; i--) {
		if(a[i]==a[n]&&r.second!=k)r.first=i,r.second++;
	}
	if(l.second!=k||r.second!=k) {
		no;
		return;
	}
	if(a[1]==a[n]) yes;
	else {
		if(l.first<r.first)yes;
		else no;
	}
}

D. Prefix Permutation Sums 

题意:

思路:求出该数组的差值后,只有两种情况是YES:
①1~n之间恰好有两个数的位置上是空的,并且恰好有一个数多余的数,等于这两个位置加起来,这样就能使得1~n填满。

②1~n之间恰好有一个数的位置上是空的。此时只需将这缺的数放到数组最后面,就能令数组合法。

void solve() {
	unordered_map<int,int>mp;
	int n,sum=0,cnt=0,now;
	cin>>n;
	for(int i=1; i<n; i++) {
		cin>>a[i];
		mp[a[i]-a[i-1]]++;
	}
	for(int i=1; i<=n; i++) {
		if(!mp[i]) {
			cnt++;
			sum+=i;
		}
	}
	for(auto x:mp) {
		if(x.second>=2||x.first>n) {
			now=x.first;
			break;
		}
	}
	if(now==sum&&cnt==2||cnt==1)yes;
	else no;
}

 E. Nastya and Potions

题意:

思路: dfs即可,第i个药水的最小价值为dfs(e[1])+dfs(e[2])+......dfs(e[m[i]))。

代码:

int dfs(int u){
	if(st[u]!=-1)return st[u];
	if(e[u].size()==0) return c[u];
	int sum=0;
	for(auto x:e[u]){
		sum+=dfs(x);
	}
	return st[u]=min(c[u],sum);
}
void solve() {
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=n;i++)cin>>c[i],e[i].clear(),st[i]=-1;
	for(int i=1;i<=k;i++){
		int x;
		cin>>x;
		c[x]=0;
	}
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		for(int j=1;j<=x;j++){
			int xx;
			cin>>xx;
			e[i].push_back(xx);
		}
	}
	for(int i=1;i<=n;i++)cout<<dfs(i)<<" \n"[i==n];
}

F. Lisa and the Martians

题意: 

思路:因为&和^操作对位与位之间不会产生影响,所以我们从单个的位来思考:若两个位不同,那么无论选择的x是什么,这个位异或x然后相与之后都会变成0。

比如第一个数是0,第二个数是1,用1来异或这两数后,第一个数变0,第二个数变1,他们两相与为0;用0来异或这两数后,第一个数还是0,第二个数还是1,他们两相与还是为0。

若两个位相同,我们则可以选择一个与该位相反的数,使这个位异或相与之后为1。

比如第一个数是0,第二个数是0,用1来异或这两数后,第一个数变1,第二个数变1,他们两相与为1;比如第一个数是1,第二个数是1,用0来异或这两数后,第一个数还是1,第二个数还是1,他们两相与还是1;

所以我们需要找到该数组的最大与或对,也就是最小异或对。

然后有一个结论:最小异或对是数组排完序之后,相邻异或和的最小值。

因此我们只需排一下序,然后遍历标记数组,就可以得到最小异或对的位置了。而x的值,可以由这个两个异或对中的任意一个,在二进制位上取反来获得。

代码:

void solve() {
	vector<PII>v;
	int n,k;
	cin>>n>>k;
	for(int i=1; i<=n; i++) {
		int x;
		cin>>x;
		v.push_back({x,i});
	}
	sort(v.begin(),v.end());
	int minn=inf,pos1,pos2,ans;
	for(int i=1; i<v.size(); i++) {
		int x=(v[i].first^v[i-1].first);
		if(x<minn) {
			minn=x;
			pos1=v[i].second,pos2=v[i-1].second,ans=v[i].first;

		}
	}
	cout<<pos1<<" "<<pos2<<" "<<((1<<k)-1-ans)<<endl;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值