Codeforces Round #648 (Div. 2) 题解 (DEF)

https://codeforces.com/contest/1365

真的没时间补ABC了,希望我的ddl没事qwqqqqqqqqqqqqqqqqqqqqqq

D. Solve The Maze

题目大意:放几个障碍物让所有好人逃出地图,让所有坏人逃不出地图

首先把坏人相邻的空格变成障碍物

  • 因为好人肯定不会经过坏人周围的空格(否则坏人顺着这个路逃走),还不如堵死

然后就看所有好人是否能逃离地图,即判断好人与逃生点的连通性。判断连通性,dfs,bfs,dsu都可

WARNING 辣鸡代码警告

#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=210; typedef long long ll;
int n,m,T;
string s[N];
bool inside(int x,int y){
	return x>=0 && y>=0 && x<n && y<m;
}
bool good(int x,int y){
	return s[x][y]=='.' || s[x][y]=='G';
}
int dn[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
queue<pair<int,int>> q;
signed main(){
	cin>>T;
	while(T--){
		cin>>n>>m; repeat(i,0,n)cin>>s[i];
		int ans=true;
		repeat(x,0,n)
		repeat(y,0,m)
		if(s[x][y]=='B'){
			repeat(k,0,4){
				int px=x+dn[k][0];
				int py=y+dn[k][1];
				if(inside(px,py)){
					if(s[px][py]=='G')ans=false;
					if(s[px][py]=='.')s[px][py]='#';
				}
			}
		}
		if(s[n-1][m-1]=='B')ans=false;
		if(good(n-1,m-1)){
			s[n-1][m-1]='o';
			q.push({n-1,m-1});
			while(!q.empty()){
				int x=q.front().first,y=q.front().second;
				q.pop();
				repeat(k,0,4){
					int px=x+dn[k][0];
					int py=y+dn[k][1];
					if(inside(px,py) && good(px,py)){
						s[px][py]='o';
						q.push({px,py});
					}
				}
			}
		}
		repeat(i,0,n)
		repeat(j,0,m)
		if(s[i][j]=='G')
			ans=false;
		cout<<(ans?"Yes":"No")<<endl;
	}
	return 0;
}

E. Maximum Subsequence Value

题目大意:选取长度为 \(k\) 的子序列,定义子序列的value为,对于二进制的某一位,子序列中该位为1的个数大于等于 \(\max(1,k-2)\),那么value的该位也为1。求所有子序列中value最大值

猛男zkx告诉我)很显然,只要 \(k\le 3\) 的情况即可。因为对于长度为4的子序列value小于等于去掉一个元素后的子序列的value(读者自证不难

然后3个for搞定

#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=510; typedef long long ll;
#define int ll
int n,a[N],ans;
signed main(){
	cin>>n;
	repeat(i,0,n)cin>>a[i];
	repeat(i,0,n)
	repeat(j,i,n)
	repeat(k,j,n)
		ans=max(ans,a[i]|a[j]|a[k]);
	cout<<ans<<endl;
	return 0;
}

F. Swaps Again

题目大意:问是否经过多次操作可以让数组a变成数组b。操作为,交换区间 \([1,k]\)\([n-k+1,n]\)\((1\le k\le \lfloor \dfrac n 2 \rfloor)\)

猛男zkx又告诉我)很显然,对于对称的两个数(\(a[i]\)\(a[n-i+1]\)),经过任意操作后,它俩还是对称的。(当然了,交换它俩还是允许的)这就很厉害了,只要把对称的数捆绑在一起,用一下set/map或者排个序都是可以的,这道F题也就很容易地被我们切掉了

#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=510; typedef long long ll;
int n,a[N],b[N],T;
map<pair<int,int>,int> mp;
signed main(){
	cin>>T;
	while(T--){
		cin>>n;
		repeat(i,0,n)cin>>a[i];
		repeat(i,0,n)cin>>b[i];
		int ans=true; mp.clear();
		if(n%2==1 && a[n/2]!=b[n/2])ans=false;
		repeat(i,0,n/2){
			int x,y;
			x=a[i],y=a[n-i-1];
			if(x>y)swap(x,y);
			mp[{x,y}]++;
			x=b[i],y=b[n-i-1];
			if(x>y)swap(x,y);
			mp[{x,y}]--;
		}
		for(auto i:mp)if(i.second!=0)ans=false;
		cout<<(ans?"Yes":"No")<<endl;
	}
	return 0;
}
posted @ 2020-06-08 01:26  axiomofchoice  阅读(131)  评论(0编辑  收藏  举报