码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #646 (Div. 2) 题解 (ABCE)

时间:2020-06-01 09:16:56      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:round   syn   nta   i++   大于等于   cti   clu   cout   put   

https://codeforces.com/contest/1363

A. Odd Selection

第一反应当然是分类讨论if到底。想了一下发现好像有点麻烦,正好n又不大所以for一下

枚举的方法,枚举原数组中取多少偶数(记为i),那么原数组中奇数就要取x-i个,只要判断x-i是否为奇数并且原数组的奇数个数是否大于等于x-i就行了

分类讨论的方法,难顶,详见代码

枚举的代码

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll;
#define int ll
int T,n,x,a[2],t;
void output(bool x){cout<<(x?"Yes":"No")<<endl;}
signed main(){
	cin>>T;
	while(T--){
		cin>>n>>x;
		a[0]=a[1]=0;
		int f=0;
		repeat(i,0,n)cin>>t,a[t%2]++;
		repeat(i,0,a[0]+1){
			if((x-i)%2==1 && a[1]>=x-i){
				output(1);
				f=1;
				break;
			}
		}
		if(!f)output(0);
	}
	return 0;
}

分类讨论的代码(转载自 %%%施老师)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
int T,n,k,x,num1,num2;
int main()
{
	scanf("%d",&T);
	while (T--)
	{
		scanf("%d%d",&n,&k); num1=0; num2=0;
		for (int i=1;i<=n;i++)
		{
			scanf("%d",&x);
			if (x&1) num1++;else num2++;
		}
		if (num1==0) printf("No\n");
		else
		{
			num1--; k--; k-=2*min(num1/2,k/2);
			if (k<=num2) printf("Yes\n");else printf("No\n");
		}
	}
return 0;	
}

B. Subsequence Hate

显而易见,s最终只有两种情况,00..0011..11和11..1100..00。我们枚举一下01分界线。为了加点速,要用前缀和记录前x个位置有多少1,这样 \(O(1)\) 询问答案,美滋滋

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll;
#define int ll
int T,n,sum[N];
string s;
int q1(int l,int r){ //询问[l,r]有多少个1
	return sum[r]-sum[l-1];
}
int q0(int l,int r){ //询问[l,r]有多少个0
	return r-l+1-q1(l,r);
}
signed main(){
	cin>>T;
	while(T--){
		cin>>s; s=‘x‘+s; 
		int n=s.size()-1;
		repeat(i,1,n+1)
			sum[i]=sum[i-1]+(s[i]==‘1‘);
		int ans=1e9;
		repeat(i,0,n+1){ //枚举分界线
			ans=min(ans,q0(1,i)+q1(i+1,n));
			ans=min(ans,q1(1,i)+q0(i+1,n));
		}
		cout<<ans<<endl;
	}
	return 0;
}

C. Game On Leaves

一般来说,双方都会尽量不让x节点的度变成小于等于1,因此这个x节点大多情况都是倒数第二个取走的。除了x节点的度已经小于等于1了

所以只要判断x节点的度是否小于等于1,再判断n的奇偶性就行了

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll;
#define int ll
int T,n,x;
signed main(){
	cin>>T;
	while(T--){
		cin>>n>>x;
		int deg=0;
		repeat(i,0,n-1){
			int u,v; cin>>u>>v;
			if(u==x || v==x)deg++;
		}
		if(deg<=1 || n%2==0)cout<<"Ayush"<<endl;
		else cout<<"Ashish"<<endl;
	}
	return 0;
}

//## D. Guess The Maximums

//事实上只要二分查找出最大值的位置(\(A[i]=n\) 的这个 \(i\)),然后,如果某一集合包含了i那就查询这个集合的补集

//等会补

//(终测没完,交不了代码呜呜呜)

大家好,没错我的方法假了

如果你觉得数组A遍历了[1,n],或者Si遍历了[1,n],或者两个地雷一起踩(正是在下),那就有可能fst惨案

E. Tree Shuffling

树型dp

我们让儿子的费用(即 \(a[i]\))赋值为\(\min\)(儿子费用,父亲费用),这样操作的好处是,如果儿子所在的子树存在需要互换的两个节点,那一定是儿子解决这个问题而不是去麻烦父亲乃至祖宗

因此只要统计每个子树的需要把0变1的节点个数,以及1变0的节点个数,然后及时计算费用,然后把这两个值传给父亲即可

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll;
#define int ll
int n,x;
vector<int> a[N];
int cost[N],b[N],c[N],ans,cnt[N][2];
void dfs(int x,int fa){
	if(fa!=-1)cost[x]=min(cost[x],cost[fa]); 
	for(auto p:a[x])
	if(p!=fa){
		dfs(p,x);
		cnt[x][0]+=cnt[p][0];
		cnt[x][1]+=cnt[p][1];
	}
	if(b[x]!=c[x])cnt[x][b[x]]++;
	int t=min(cnt[x][0],cnt[x][1]);
	ans+=2*t*cost[x];
	cnt[x][0]-=t;
	cnt[x][1]-=t;
}
signed main(){
	cin>>n;
	repeat(i,0,n)cin>>cost[i]>>b[i]>>c[i];
	repeat(i,0,n-1){
		int x,y; cin>>x>>y; x--,y--;
		a[x].push_back(y);
		a[y].push_back(x);
	}
	dfs(0,-1);
	if(cnt[0][0] || cnt[0][1])cout<<-1<<endl;
	else cout<<ans<<endl;
	return 0;
}

Codeforces Round #646 (Div. 2) 题解 (ABCE)

标签:round   syn   nta   i++   大于等于   cti   clu   cout   put   

原文地址:https://www.cnblogs.com/axiomofchoice/p/13022886.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!