状态:
f
[
i
]
[
j
]
f[i][j]
f[i][j] 表示要保证第
i
i
i 天的自信值至少为
j
j
j ,则前
i
i
i 天内最多可以不刷题几天
转移非常显然
f
[
0
]
[
j
]
=
0
,
0
≤
j
≤
m
c
f[0][j]=0,0\le j\le mc
f[0][j]=0,0≤j≤mc
f
[
i
]
[
j
−
a
i
]
=
max
(
f
[
i
]
[
j
−
a
i
]
,
f
[
i
−
1
]
[
j
]
+
1
)
f[i][j-a_i]=\max(f[i][j-a_i],f[i-1][j]+1)
f[i][j−ai]=max(f[i][j−ai],f[i−1][j]+1)
f
[
i
]
[
min
(
m
c
,
j
−
a
i
+
w
i
)
]
=
max
(
f
[
i
]
[
min
(
m
c
,
j
−
a
i
+
w
i
)
]
,
f
[
i
−
1
]
[
j
]
)
f[i][\min(mc,j-a_i+w_i)]=\max(f[i][\min(mc,j-a_i+w_i)],f[i-1][j])
f[i][min(mc,j−ai+wi)]=max(f[i][min(mc,j−ai+wi)],f[i−1][j])
求出
n
d
a
y
s
ndays
ndays 表示最多可以用多少天来打伤害
n
d
a
y
s
=
max
i
=
1
n
max
j
=
0
m
c
f
[
i
]
[
j
]
ndays=\max_{i=1}^n\max_{j=0}^{mc}f[i][j]
ndays=i=1maxnj=0maxmcf[i][j]
然后考虑打伤害
利用 BFS + 哈希表预处理出一些二元组
(
d
,
f
)
(d,f)
(d,f) 构成的集合
这些二元组
(
d
,
f
)
(d,f)
(d,f) 的意义是可以用
d
d
d 天(包括升等级,提升讽刺能力,以及这
d
d
d 天的最后一天怼大佬,
d
≤
n
d
a
y
s
d\le ndays
d≤ndays )使大佬的自信值降低
f
f
f
可以发现这样的
(
d
,
f
)
(d,f)
(d,f) 数量是可以接受的
然后每个大佬分三种情况:
(1)不怼大佬,只使用普攻。即判断是否
C
≤
n
d
a
y
s
C\le ndays
C≤ndays 。
(2)怼一次大佬。即判断是否存在一个二元组
(
d
,
f
)
(d,f)
(d,f) 满足:
①
f
≤
C
f\le C
f≤C (自信值不能为负数)
②
f
+
n
d
a
y
s
−
d
≥
C
f+ndays-d\ge C
f+ndays−d≥C (在剩下的至多
n
d
a
y
s
−
d
ndays-d
ndays−d 内使用普攻)
(3)这也是重点:怼两次大佬。
将所有的二元组按照
f
f
f 为关键字从小到大排序,然后枚举第一次怼大佬的二元组
(
d
1
,
f
1
)
(d_1,f_1)
(d1,f1) ,然后这时候需要满足的第二次怼大佬情况
(
d
2
,
f
2
)
(d_2,f_2)
(d2,f2) 需要满足
f
1
+
f
2
≤
C
f_1+f_2\le C
f1+f2≤C
f
1
+
f
2
+
n
d
a
y
s
−
d
1
−
d
2
≥
C
f_1+f_2+ndays-d_1-d_2\ge C
f1+f2+ndays−d1−d2≥C
先考虑第一个条件,显然排序之后合法的
f
2
f_2
f2 是一段前缀并且随着
f
1
f_1
f1 的增大而减小。所以按照
f
f
f倒序枚举二元组之后 two pointers 维护
f
2
f_2
f2 合法的二元组前缀即可
而对于第二个条件,移项后可得
C
−
f
1
−
n
d
a
y
s
+
d
1
≤
f
2
−
d
2
C-f_1-ndays+d_1\le f_2-d_2
C−f1−ndays+d1≤f2−d2
设当前
f
2
f_2
f2 合法的前缀是第
1
1
1 个二元组到第
k
k
k 个二元组
那么我们要做的就是在前
k
k
k 个二元组中找出一个最大
f
−
d
f-d
f−d 作为第二次怼大佬的结果
也就是这时候要判断是否
C
−
f
1
−
n
d
a
y
s
+
d
1
≤
max
i
=
1
k
{
f
(
i
)
−
d
(
i
)
}
C-f_1-ndays+d_1\le\max_{i=1}^k\{f_{(i)}-d_{(i)}\}
C−f1−ndays+d1≤i=1maxk{f(i)−d(i)}
上面排序后第
i
i
i 个二元组为
(
d
(
i
)
,
f
(
i
)
)
(d_{(i)},f_{(i)})
(d(i),f(i))
完美解决
Code
#include<map>#include<cmath>#include<queue>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define For(i, a, b) for (i = a; i <= b; i++)#define Rof(i, a, b) for (i = a; i >= b; i--)inlineintread(){int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}template<classT>inline T Max(const T &a,const T &b){return a > b ? a : b;}template<classT>inline T Min(const T &a,const T &b){return a < b ? a : b;}constint N =105, M =3e6+5, ZZQ =19260817;int n, m, mc, a[N], w[N], f[N][N], ndays, len, C, maxfd[M];struct node
{int l, f;friendinlinebooloperator<(node a, node b){return a.l < b.l ||(a.l == b.l && a.f < b.f);}};struct juruo
{
node ct;int dis;};struct dalao
{int d, f;} q[M];inlineboolcomp(const dalao &a,const dalao &b){return a.f < b.f;}
std::map<node,int> orz;
std::queue<juruo> que;voidbfs(){int i;
orz[(node){0,1}]=1;
que.push((juruo){(node){0,1},0});
q[len =1]=(dalao){1,1};while(!que.empty()){
juruo u = que.front(); que.pop();if(u.dis < ndays){if(!orz[(node){u.ct.l +1, u.ct.f}]){
orz[(node){u.ct.l +1, u.ct.f}]=1;
juruo nw;
nw.ct =(node){u.ct.l +1, u.ct.f};
nw.dis = u.dis +1;
que.push(nw);}if(u.ct.l &&1ll* u.ct.l * u.ct.f <=1000000000&&!orz[(node){u.ct.l, u.ct.l * u.ct.f}]){
orz[(node){u.ct.l, u.ct.l * u.ct.f}]=1;
juruo nw;
nw.ct =(node){u.ct.l, u.ct.l * u.ct.f};
nw.dis = u.dis +1;
q[++len]=(dalao){nw.dis +1, nw.ct.f};
que.push(nw);}}}
std::sort(q +1, q + len +1, comp);
maxfd[1]= q[1].f - q[1].d;
For (i,2, len) maxfd[i]=Max(maxfd[i -1], q[i].f - q[i].d);}intmain(){int i, j, p;
n =read(); m =read(); mc =read();
For (i,1, n) a[i]=read();
For (i,1, n) w[i]=read();
For (i,1, n){
For (j, a[i], mc){
f[i][j - a[i]]=Max(f[i][j - a[i]], f[i -1][j]+1);
f[i][Min(mc, j - a[i]+ w[i])]=Max(f[i][Min(mc, j - a[i]+ w[i])], f[i -1][j]);}
For (j,0, mc) ndays =Max(ndays, f[i][j]);}bfs();while(m--){
C =read();bool res =0;if(!ndays){puts("0");continue;}if(C <= ndays){puts("1");continue;}
For (i,1, len)if(q[i].f <= C && C - q[i].f <= ndays - q[i].d){res =1;break;}if(res){puts("1");continue;}
p =1;
Rof (i, len,1){while(p <= len && q[i].f + q[p].f <= C) p++;if(p >1&& C - ndays + q[i].d - q[i].f <= maxfd[p -1]){
res =1;break;}}puts(res ?"1":"0");}return0;}