题意:你有n个纸条,现在你要用0和1去写满这些纸条(每个纸条只能写一行),每个纸条都给出了一个x和一个y,表示要求写的0的数量和1的数量,并且规定任何时候都不能有超过k个0连续,任何时候都不能有超过k个1连续,注意假设写完一个纸条和它后一个纸条是连续的,也就是说一个纸条末尾的0或1也要算在它后一个纸条的开头。

1<=n<=3e5,1<=k<=1e6,1<=x<=1e6,1<=y<=1e6

思路:一步一步来,首先不考虑两个纸条之间的影响,只考虑一个纸条,假设要放x个0和y个1,限制为k,如何使其可行?方案太多了,但是众多方案中肯定有一些是不优的,我们只要尽量好的方案,所以得到这样的状态:当前纸条有可行方案并且末尾的0最少,当前纸条有可行方案并且末尾的1最少,想一下就能明白这就是我们每次递推所要求的最优状态,所以设dp【i】【0/1】为推到第i个纸条有合法方案时末尾0数量的最小值/末尾1数量的最小值

转移方程算是个情况大讨论,这里仅提示几点,首先考虑开头放0还是放1,然后考虑x > y, x = y, x < y,接着考虑x(y)除以k的商与y(x)的关系,特判一下余数什么的就好了,比较繁琐。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;
const int INF = 0x3f3f3f3f;
int n, k;
int x[maxn], y[maxn];
int dp[maxn][2];
void update(int idx, int v1, int v2) {
dp[idx][0] = min(dp[idx][0], v1);
dp[idx][1] = min(dp[idx][1], v2);
}
void update0(int x, int y, int idx) {
if (x > y) {
int d = x / k, r = x % k;
if (r == 0) {
if (y < d-1) update(idx, INF, INF);
else if (y == d-1) update(idx, k, INF);
else update(idx, 1, 1);
}
else {
if (y < d) update(idx, INF, INF);
else if (y == d) update(idx, r, INF);
else update(idx, 1, 1);
}
}
else if (x == y) {
update(idx, INF, 1);
}
else {
int d = y / k, r = y % k;
if (r == 0) {
if (x < d) update(idx, INF, INF);
else if (x == d) update(idx, INF, k);
else update(idx, 1, 1);
}
else {
if (x < d+1) update(idx, INF, INF);
else if (x == d+1) update(idx, INF, r);
else update(idx, 1, 1);
}
}
}
void update1(int x, int y, int idx) {
if (x > y) {
int d = x / k, r = x % k;
if (r == 0) {
if (y < d) update(idx, INF, INF);
else if (y == d) update(idx, k, INF);
else update(idx, 1, 1);
}
else {
if (y < d+1) update(idx, INF, INF);
else if ( y == d+1) update(idx, r, INF);
else update(idx, 1, 1);
}
}
else if (x == y) {
update(idx, 1, INF);
}
else {
int d = y / k, r = y % k;
if (r == 0) {
if (x < d-1) update(idx, INF, INF);
else if (x == d-1) update(idx, INF, k);
else update(idx, 1, 1);
}
else {
if (x < d) update(idx, INF, INF);
else if (x == d) update(idx, INF, r);
else update(idx, 1, 1);
}
}
}
void solve() {
memset(dp, INF, sizeof(dp));
dp[0][0] = dp[0][1] = 0;
update0(x[1], y[1], 1);
update1(x[1], y[1], 1);
for (int i = 2; i <= n; i++) {
if (dp[i-1][0] != INF) {
if (x[i]-(k-dp[i-1][0]) <= 0) {
update0(x[i], y[i], i);
update1(x[i], y[i], i);
}
else {
if (x[i] - (k-dp[i-1][0]) > 0) update1(x[i]-(k-dp[i-1][0]), y[i], i);
update1(x[i], y[i], i);
}
}
if (dp[i-1][1] != INF) {
if (y[i]-(k-dp[i-1][1]) <= 0) {
update0(x[i], y[i], i);
update1(x[i], y[i], i);
}
else {
update0(x[i], y[i], i);
if (y[i]-(k-dp[i-1][1]) > 0) update0(x[i], y[i]-(k-dp[i-1][1]), i);
}
}
}
}
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) scanf("%d", &x[i]);
for (int i = 1; i <= n; i++) scanf("%d", &y[i]);
solve();
if (dp[n][0] == INF && dp[n][1] == INF) puts("NO");
else puts("YES");
return 0;
}