专栏文章

Atcoder ABC 386

题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@miqmgwu5
此快照首次捕获于
2025/12/04 07:12
3 个月前
此快照最后确认于
2025/12/04 07:12
3 个月前
查看原文
是否所有黑色块都在白色块的上方或者左方。
CPP
#include<bits/stdc++.h>
using namespace std;
const int N = 200005;
struct node{
	int x, y;
	char val;
}mp[N];
bool cmp(node x, node y){
	return x.x == y.x ? x.y < y.y : x.x < y.x;
} // 先按x排,再按y排 
int main(){
	int n, m;
	cin >> n >> m;
	for(int i = 1; i <= m; i++)
		cin >> mp[i].x >> mp[i].y >> mp[i].val;
		
	sort(mp + 1, mp + m + 1, cmp);
	
	int now = n; // 表示当前最小的W的边界 
	
	for(int i = 1; i <= m; i++){ // x以保证有序,维护当前最小的y 
		if(mp[i].val == 'W') 
			now = min(now, mp[i].y - 1);
		else{
			if(mp[i].y > now){ // 破坏性的'B' 
				cout << "No";
				return 0;
			}
		}
	}
	cout<<"Yes";
	return 0;
}
题目保证了(NK)106\dbinom{N}{K}\leq 10^6,所以可以爆搜所有情况,然后取maxmax
CPP
#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2e5 + 5;
int n, k;
LL a[N], ans;

void dfs(int k, int i, LL cur) {
    if (k + i > n + 1) return;
    if (k == 0) {
        ans = max(ans, cur);
        return;
    }
    dfs(k - 1, i + 1, cur ^ a[i]);
    dfs(k, i + 1, cur);
}
int main() {
    cin >> n >> k;
    LL base = 0;
    for(int i = 1; i <= n; i++) cin >> a[i], base ^= a[i];
    if (k + k > n) k = n - k; else base = 0;
    // k+k>n 相当于再base中去掉n-k个数 
    dfs(k, 1, base);
    cout << ans << endl;
    return 0; 
}

经典动归,字符串编辑距离的改编。
SS的前ii个字符,TT的前jj个字符相等的最少操作次数。
SSTT的变化不超过2020步,所以实际在计算ii转移的时候,jj的范围应该是在[i20,i+20][i - 20, i + 20]
那么时空复杂度都降成了S×k|S| \times k.
CPP
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int n, m, k;
char s[N], t[N];
int dp[N][50];

int main(){
	scanf("%d", &k);
	scanf("%s", s); scanf("%s", t);
	
	n = strlen(s), m = strlen(t);
	if(abs(n - m) > 20) {
		puts("No");
		return 0;
	}
	
	memset(dp, 0x3f, sizeof dp);
	
	dp[0][20] = 0;
	
	for(int i = 0; i <= n; i++) // s的前i个字符 
		for(int d = 0; d <= 40; d++){// s的位置与t的位置的相对差值 
			int j = i + d - 20;// j表示在t中的前j个字符 
			if(j < 0 || j > m) continue;
			if(i >= 1 && j >= 1)
				dp[i][d] = min(dp[i][d], dp[i - 1][d] + (s[i - 1] != t[j - 1])); //修改 
			if(i >= 1)
				dp[i][d] = min(dp[i][d], dp[i - 1][d + 1] + 1); // 删除
			if(j >= 1) 
				dp[i][d] = min(dp[i][d], dp[i][d - 1] + 1); // 插入 
		}
	
	if(dp[n][m - n + 20] <= k)
		puts("Yes");
	else
		puts("No"); 
	return 0;
}


 

评论

1 条评论,欢迎与作者交流。

正在加载评论...