Link
Diffculty
算法难度5,思维难度6,代码难度6
Description
由于题面过于复杂,这里就不贴了,自己看链接吧。。。
Solution
首先我们可以dp求出可以自由支配的最大天数 d d d,直接 d p ( i , j ) dp(i,j) dp(i,j)代表第 i i i天,血量为 j j j,所能自由支配的最大天数。
然后我们考虑 b f s bfs bfs求出所有合法二元组 ( F , C ) (F,C) (F,C),代表打出伤害 F F F最少需要 C C C天,这里需要注意map判重,不然会挂的非常惨。
对于一个血量为
T
T
T的大佬,符合条件的两个二元组一定满足这两个不等式:
F
i
+
F
j
≤
T
,
F
i
+
F
j
+
d
−
C
i
−
C
j
−
2
≥
T
F_i+F_j\le T,F_i+F_j+d-C_i-C_j-2\ge T
Fi+Fj≤T,Fi+Fj+d−Ci−Cj−2≥T
那么我们将二元组按照
F
i
F_i
Fi排序,令
F
i
F_i
Fi递减,那么符合条件的
F
j
F_j
Fj一定递增,观察后面的式子,发现我们只需要维护
F
j
−
C
j
F_j-C_j
Fj−Cj的最大值即可,直接
t
w
o
two
two
p
o
i
n
t
e
r
pointer
pointer扫一下就好了。
时间复杂度真心玄学。。。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#define LL long long
using namespace std;
inline int read(){
int x=0,f=1;char ch=' ';
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9')x=x*10+(ch^48),ch=getchar();
return f==1?x:-x;
}
typedef pair<int,int> pii;
const int N=105,M=1e7;
struct data{int F,L,C;};
int n,m,mc,d,cnt,a[N],w[N];
int dp[N][N];
queue<data> q;
map<pii,int> vis;
struct data2{
int x,y;
bool operator < (const data2& b) const {return x<b.x;}
}Q[M];
inline bool solve(int C){
if(C<=d)return 1;
int j=0,mx=-1e9;
for(int i=cnt;i>=1;--i){
if(Q[i].x<=C && d>Q[i].y && C-Q[i].x<=d-Q[i].y-1)return 1;
while(j<cnt && Q[i].x+Q[j+1].x<=C){
j++;
mx=max(mx,Q[j].x-Q[j].y);
}
if(Q[i].x-Q[i].y+mx+d-2>=C)return 1;
}
return 0;
}
int main(){
memset(dp,-1,sizeof dp);
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();
dp[0][mc]=0;
for(int i=0;i<n;++i){
for(int j=0;j<=mc;++j){
if(dp[i][j]<0)continue;
int t=j-a[i+1];if(t<0)continue;
dp[i+1][t]=max(dp[i+1][t],dp[i][j]+1);
t=min(t+w[i+1],mc);
dp[i+1][t]=max(dp[i+1][t],dp[i][j]);
}
}
for(int i=1;i<=n;++i)for(int j=0;j<=mc;++j)d=max(d,dp[i][j]);
q.push((data){1,0,0});
while(!q.empty()){
data x=q.front();
q.pop();
if(x.C>d-1)continue;
else if(x.C==d-1){Q[++cnt]=(data2){x.F,x.C};continue;}
else Q[++cnt]=(data2){x.F,x.C};
if(x.L && (LL)x.F*x.L<=1e8 && !vis[pii(x.F*x.L,x.L)]){
q.push((data){x.F*x.L,x.L,x.C+1});
vis[pii(x.F*x.L,x.L)]=x.C+1;
}
if(!vis[pii(x.F,x.L+1)]){
q.push((data){x.F,x.L+1,x.C+1});
vis[pii(x.F,x.L+1)]=x.C+1;
}
}
sort(Q+1,Q+cnt+1);
for(int s=1;s<=m;++s){
int C=read();
if(solve(C))printf("1\n");
else printf("0\n");
}
return 0;
}