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

题意: 

Codeforces Round 888 (Div. 3) A~F_第1张图片

 思路:暴力枚举楼梯可以造成的所有差值,然后判断即可。注意楼梯造成的差值最小为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

 B. Parity Sort

题意:Codeforces Round 888 (Div. 3) A~F_第2张图片

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

代码:

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

题意:Codeforces Round 888 (Div. 3) A~F_第3张图片

思路:只要有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

D. Prefix Permutation Sums 

题意:Codeforces Round 888 (Div. 3) A~F_第4张图片

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

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

void solve() {
	unordered_mapmp;
	int n,sum=0,cnt=0,now;
	cin>>n;
	for(int i=1; i>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

题意:

Codeforces Round 888 (Div. 3) A~F_第5张图片

思路: 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<

F. Lisa and the Martians

题意: 

Codeforces Round 888 (Div. 3) A~F_第6张图片思路:因为&和^操作对位与位之间不会产生影响,所以我们从单个的位来思考:若两个位不同,那么无论选择的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() {
	vectorv;
	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

你可能感兴趣的:(codeforces题解,算法,c++,数据结构)