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;
}