题目大意:
洛谷
解题思路:
- 五种操作中只有一种与自己的自信值有关,而其他四种的操作在第i天操作或第j天操作都一样(假设只操作一次),即这四种操作跟第几天无关
- 所以可以先通过
d
p
dp
dp来求出自己最大的存活天数,再在天数上面做操作
- 设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]为第
i
i
i天
j
j
j自信的最大存活天数,则可以通过
O
(
n
2
)
O(n^2)
O(n2)即可求醉最大存活天数
- 问题就转换为:给你n天,能否怼死大佬
- 而怼大佬只与天数和嘲讽值有关,那么先直接BFS+Map判重枚举出所有状态
- 按照嘲讽值从大到小排序就行,要满足
f
1
+
f
2
≤
C
,
f
1
+
f
2
+
(
D
−
d
1
−
d
2
)
≥
C
f_1+f_2\le C, f_1+f_2+(D-d_1-d_2)\ge C
f1+f2≤C,f1+f2+(D−d1−d2)≥C
- 先固定
f
i
f_i
fi,那么
f
i
,
d
i
,
D
,
C
f_i,d_i,D,C
fi,di,D,C也知晓,只是要
f
2
−
d
2
f_2-d_2
f2−d2的最大值
- 如果暴力的话就是
O
(
状
态
数
2
)
O(状态数^2)
O(状态数2),但是因为已经排好序,所以直接双指针头尾就行(具体可看代码注释)
AC代码:
#include <bits/stdc++.h>
#define ft first
#define sd second
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define seteps(N) fixed << setprecision(N)
#define endl "\n"
const int maxn = 1e2 + 10;
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> pii;
const ll mod = 1e9 + 7;
ll qpow(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
int n, m, mc, day, mx;
int a[maxn], w[maxn], c[maxn], dp[maxn][maxn];
struct Node {
int i, f, l;
};
queue <Node> q;
map <pii, bool> vis;
int cntz;
pii zt[1000100];
void bfs() {
q.push({1, 1, 0});
while (!q.empty()) {
Node u = q.front(); q.pop();
if (u.i == day) continue;
q.push({u.i + 1, u.f, u.l + 1});
if (u.l > 1 && 1ll * u.f * u.l <= 1ll * mx && !vis.count({u.f * u.l, u.i + 1})) {
q.push({u.i + 1, u.f * u.l, u.l});
zt[++cntz] = {u.f * u.l, u.i + 1};
vis[{u.f * u.l, u.i + 1}] = true;
}
}
}
int main() {
IOS;
cin >> n >> m >> mc;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> w[i];
for (int i = 1; i <= m; i++) cin >> c[i], mx = max(mx, c[i]);
for (int i = 1; i <= n; i++)
for (int j = a[i]; j <= mc; j++) {
dp[i][j - a[i]] = max(dp[i - 1][j] + 1, dp[i][j - a[i]]);
dp[i][min(j - a[i] + w[i], mc)] = max(dp[i - 1][j], dp[i][min(j - a[i] + w[i], mc)]);
}
for (int i = 1; i <= n; i++)
for (int j = 0; j <= mc; j++)
day = max(day, dp[i][j]);
bfs();
sort (zt + 1, zt + cntz + 1);
for (int i = 1; i <= m; i++) {
if (c[i] <= day) {
cout << 1 << endl;
continue;
}
bool ok = false;
int mmin = 1e9;
for (int j = cntz, k = 1; j >= 1; j--) {
while (k < cntz && zt[k].ft + zt[j].ft <= c[i])
mmin = min(mmin, zt[k].sd - zt[k].ft), ++k;
if (zt[j].ft + day - zt[j].sd - mmin >= c[i]) {ok = true; break;}
if (zt[j].ft <= c[i] && c[i] - zt[j].ft <= day - zt[j].sd) {ok = true; break;}
}
ok ? cout << 1 << endl : cout << 0 << endl;
}
return 0;
}