观察发现,我们加血和攻击是两个互不影响的操作,只要保证我们时刻存活就可以进行攻击,而攻击又有一些约束条件,方便起见,我们设置三个子任务 s u b t a s k subtask subtask
- s u b t a s k 1 : subtask1: subtask1:处理出,保证自己存活的情况下,可以有多少天自由行动(不回血)
- s u b t a s k 2 : subtask2: subtask2:在完成 s u b t a s k 1 subtask1 subtask1后处理出,自由行动的时候,花多少天能够对大佬造成多少伤害,要具体到每一个可能数值上,因为只能把血打成0,这里只考虑攻击一次
- s u b t a s k 3 : subtask3: subtask3:在完成 s u b t a s k 2 subtask2 subtask2后,我们能否击败每个大佬
对于
s
u
b
t
a
s
k
1
subtask1
subtask1,一个简单dp即可
对于
s
u
b
t
a
s
k
2
subtask2
subtask2,搜索一下,map或者hash判重
对于
s
u
b
t
a
s
k
3
subtask3
subtask3,我们分析一下限制条件,写成不等式得到:
对
于
两
次
攻
击
(
d
1
,
f
1
)
,
(
d
2
,
f
2
)
(
d
:
天
数
,
f
:
嘲
讽
力
)
对于两次攻击(d1,f1),(d2,f2) (d:天数,f:嘲讽力)
对于两次攻击(d1,f1),(d2,f2)(d:天数,f:嘲讽力)
1.
c
[
i
]
≥
f
1
+
f
2
(
不
能
把
血
打
成
负
数
)
1.c[i]\geq f1+f2 (不能把血打成负数)
1.c[i]≥f1+f2(不能把血打成负数)
2.
D
−
d
1
−
d
2
≥
c
[
i
]
−
f
1
+
f
2
(
要
打
死
,
剩
下
的
要
通
过
顶
嘴
打
掉
,
D
为
可
自
由
行
动
的
天
数
)
2.D-d1-d2 \geq c[i]-f1+f2 (要打死,剩下的要通过顶嘴打掉,D为可自由行动的天数)
2.D−d1−d2≥c[i]−f1+f2(要打死,剩下的要通过顶嘴打掉,D为可自由行动的天数)
把二式移项,令D单独在左边,枚举
d
1
−
f
1
d1-f1
d1−f1,则如果
f
f
f为有序,那么根据一式便满足单调性,要求
d
2
−
f
2
d2-f2
d2−f2的最小值就很好求了
特殊情况:如果可以直接嘴炮打死,就直接输出1
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=105,INF=990000000;
struct fxxk{int day,F,L;};
map<int,int>mp[N];
pair<int,int>s[2000005];
int n,m,f[N][N],w[N],a[N],mc,D=0,c[N],lim,cnt=0;
inline void dp(){
memset(f,128,sizeof(f));f[0][mc]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=mc-a[i];j++){
f[i][min(mc,j+w[i])]=max(f[i][min(mc,j+w[i])],f[i-1][j+a[i]]);
f[i][j]=max(f[i][j],f[i-1][j+a[i]]+1);
D=max(D,f[i][j]);
}
}
inline void bfs(int tot){
queue<fxxk>q;q.push((fxxk){1,1,0});
while(!q.empty()){
fxxk x=q.front();q.pop();
if(x.day<tot){
q.push((fxxk){x.day+1,x.F,x.L+1});
if(x.L>1 && x.F<lim/x.L && !mp[x.L][x.L*x.F]){
fxxk y=(fxxk){x.day+1,x.F*x.L,x.L};
mp[x.L][x.L*x.F]=1;
s[++cnt]=make_pair(y.F,y.day);q.push(y);
}
}
}
}
int main(){
n=read();m=read();mc=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) w[i]=read();
for(int i=1;i<=m;i++) c[i]=read(),lim=max(lim,c[i]);
dp();
bfs(D);sort(s+1,s+cnt+1);
for(int i=1;i<=m;i++){
int ans=0,minn=INF;
if(c[i]<D){puts("1");continue;}
for(int j=cnt,k=1;j;j--){
while(k<=cnt && s[k].first+s[j].first<=c[i]) minn=min(minn,s[k].second-s[k].first),k++;
if(minn+c[i]-s[j].first+s[j].second<=D){ans=1;break;}
if(s[j].first<=c[i] && s[j].second+c[i]-s[j].first<=D) {ans=1;break;}
}
cout<<ans<<"\n";
}
return 0;
}