Codeforces Round #648 (Div. 2) A ~ E 题解

A. Matrix Game

好像不少人(包括我) 一开始都看错题意了…

It is “share a row or column” not “share sides”.

解法: 暴力即可

Code:

int a[MX][MX];
bool r[MX],c[MX];
int n,m;
bool sol(){
	for(int i = 1;i <= n;++i){
		for(int j = 1;j <= m;++j){
			if(!r[i] && !c[j]) {
				r[i] = c[j] = true;return true;
			}
		}
	}return false;
}
int main(){
	int T;scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		clr(r,false);clr(c,false);
		for(int i = 1;i <= n;++i){
			for(int j = 1;j <= m;++j){
				scanf("%d",&a[i][j]);
				if(a[i][j]) r[i] = c[j] = true;
			}
		}
		int res = 0;
		while(true){
			if(sol()){res++;}
			else break;
		}
		if(res % 2 == 1) printf("Ashish\n");
		else printf("Vivek\n"); 
	}
	return 0;
}

B. Trouble Sort

解法: 容易发现只要不是只有Type 0 或 Type 1 就一定可以排好序,当然如果原本有序也可

Code:

int a[MX];
int b[MX];
int main(){
	int T;scanf("%d",&T);
	while(T--){int n;
		int cnt1 = 0,cnt2 = 0;
		scanf("%d",&n);
		for(int i = 1;i <= n;++i) scanf("%d",&a[i]);
		for(int i = 1;i <= n;++i) {scanf("%d",&b[i]);if(b[i]) cnt1++;else cnt2++;}
		if(cnt1 == 0 || cnt2 == 0){
			bool flag = true;
			for(int i = 2;i <= n;++i){
				if(a[i] < a[i-1]) {flag = false;break;}
			}
			if(flag) printf("Yes\n"); else printf("No\n");
		} else printf("Yes\n");
	}
	return 0;
}

C. Rotation Matching

解法:
注意到:
1.没必要a和b都操作,只需要操作其中一个就行
2.可以只向某个方向偏移一次,偏移量为 [ 1 , n ] [1, n] [1,n]

因为是n的排列,所以可以先记录下1 ~ n 每个值若要与另一个序列中的它匹配,所需要向左/右 的偏移量x,同时记录向左/右偏移量为 x 时所能匹配上的元素个数。

最后枚举向左/右的偏移量,找到在当前偏移量下的最大贡献即可。

Code:

int a[MX],posa[MX];
int b[MX],posb[MX];
int d1[MX],d2[MX];
int num1[MX],num2[MX];

int main(){
	int n;scanf("%d",&n);
	for(int i = 1;i <= n;++i){
		scanf("%d",&a[i]);
		posa[a[i]] = i;
	}
	for(int i = 1;i <= n;++i){
		scanf("%d",&b[i]);
		posb[b[i]] = i;
	}
	for(int i = 1;i <= n;++i){
		int p1 = posa[i],p2 = posb[i];
		if(p2 >= p1){
			d1[i] = p2 - p1;
			d2[i] = p1 + (n - p2);
		} else{
			d1[i] = (n-p1) + p2;
			d2[i] = p1 - p2;
		}
		num1[d1[i]]++;
		num2[d2[i]]++;
	}
	int res = 0;
	for(int i = 1;i <= n;++i){
		res = max(res,num1[i]);
		res = max(res,num2[i]);
	}
	printf("%d\n", res);
	return 0;
}

D. Solve The Maze

解法:
显然如果一开始所有好人都无法逃脱,则输出No
否则,只需要把所有坏人的周围的空位置堵住即可

粗略证明:
如果一种可行策略中,某个坏人周围 (四个方向相邻的位置) 有未被堵住的位置 ( i , j ) (i,j) (i,j),则从 ( i , j ) (i,j) (i,j) 一定无法逃脱
首先此处一定不会是好人(否则好人也无法逃脱,就不是可行策略了);
那么在此基础上再堵住此处,对可行性没有影响

都堵上之后,每个坏人也自然都无法逃脱
如果堵住了某个坏人的周围,使得某个好人也无法逃脱,则说明无论如何都无法符合条件
(说明某个好人要逃脱必须经过某个坏人的周围,要使得该好人逃脱必须同时让该坏人也能逃脱)

最后在判断是否符合条件即可

Code:

int n,m;
char mp[MX][MX];

struct node{
	int x,y;
};

int tox[] = {1,-1,0,0};
int toy[] = {0,0,-1,1};

bool judge(int x,int y){
	if(x < 1 || y < 1 || x > n || y > m) return false;
	if(mp[x][y] == '#') return false;
	return true;
}
bool check(){
	bool vis[MX][MX];clr(vis,false);
	queue<node>q;
	while(!q.empty()) q.pop();
	if(mp[n][m] != '#') {q.push((node){n,m});vis[n][m] = true;}
	while(!q.empty()){
		node now = q.front();q.pop();
		for(int i = 0;i < 4;++i){
			int nx = now.x + tox[i];
			int ny = now.y + toy[i];
			if(vis[nx][ny]) continue;
			if(judge(nx,ny)){
				vis[nx][ny] = true;
				q.push((node){nx,ny});
			}
		}
	}
	for(int i = 1;i <= n;++i){
		for(int j = 1;j <= m;++j){
			if(mp[i][j] == 'G' && vis[i][j] == false) return false;
		}
	}
	//debug1("True");
	return true;
}
bool check2(){
	bool vis[MX][MX];clr(vis,false);
	queue<node>q;
	while(!q.empty()) q.pop();
	if(mp[n][m] != '#') {q.push((node){n,m});vis[n][m] = true;}
	while(!q.empty()){
		node now = q.front();q.pop();
		for(int i = 0;i < 4;++i){
			int nx = now.x + tox[i];
			int ny = now.y + toy[i];
			if(vis[nx][ny]) continue;
			if(judge(nx,ny)){
				vis[nx][ny] = true;
				q.push((node){nx,ny});
			}
		}
	}
	for(int i = 1;i <= n;++i){
		for(int j = 1;j <= m;++j){
			if(mp[i][j] == 'B' && vis[i][j] == true) return false;
		}
	}

	return true;
}
bool solve(){
	if(!check()) return false;
	for(int i = 1;i <= n;++i){
		for(int j = 1;j <= m;++j){
			if(mp[i][j] == 'B'){
				if(j != 1 && mp[i][j-1] == '.') mp[i][j-1] = '#';
				if(j != m && mp[i][j+1] == '.') mp[i][j+1] = '#';
				if(i != 1 && mp[i-1][j] == '.') mp[i-1][j] = '#';
				if(i != n && mp[i+1][j] == '.') mp[i+1][j] = '#';
			}
		}
	}
	if(check() && check2()) return true;
	else return false;
}
void init(){
	for(int i = 1;i <= n;++i){
		for(int j = 1;j <= m;++j){
			mp[i][j] = 0;
		}
	}
}
int main(){
	int T;scanf("%d",&T);
	while(T--){
		scanf("%d %d",&n,&m);init();
		for(int i = 1;i <= n;++i){
			scanf("%s",mp[i]+1);
		}
		if(solve()) printf("Yes\n"); else printf("No\n");
	}
	return 0;
}

E. Maximum Subsequence Value

题解:
因为题目中说

at least max(1,k−2) elements of the subsequence have the i-th bit set in their binary representation

所以对于任何长度小于等于3的子序列,它的贡献为每个元素之间按位或
而任何长度大于3的子序列,其贡献不会大于它之中某个长度小于等于3的子序列
所以我们只需要取最多长度为3的子序列即可

Code:

ll a[MX];
int main(){
	int n;cin >> n;
	ll res = 0;
	for(int i = 1;i <= n;++i) cin >> a[i];
	for(int i = 1;i <= n;++i){
		for(int j = i;j <= n;++j){
			for(int k = j;k <= n;++k){
				res = max(res,a[i] | a[j] | a[k]);
			}
		}
	}
	cout << res << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值