\(ProblemLink\)
在题解的滋养下
我们观察到你的自信值并不会因为你去执行1,3,4,5操作而被影响。
而且1,3,4,5操作也与操作时的天数无关。
于是我们可以先做一个简单\(dp\),让你刷水题的次数尽量少。
\(f[i][j]\)代表在第\(i\)天还活着,且自信值为\(j\)的最多能空出的执行其他操作的天数。
\(dp\)方程如下
不刷水题
\(f[i][j-a[i]]=max(f[i][j-a[i]],f[i-1][j]+1)\)
刷水题
\(f[i][min(j-a[i]+w[i],mc)]=max(f[i-1][j],f[i][min(j-a[i]+w[i],mc)])\)
最后扫一遍,得出最多的空闲天数\(D\)
问题就变成了给你D天自由操作,你能否怼赢大佬。
这时我们先搜索一遍,把所有的可能状态二元组(伤害,所需天数)搜索出来,按伤害排序
设伤害为\(f_i\),耗时为\(s_i\)
我们有三种选择,
一、不怼大佬。
判断\(D>=C\)即可。
二、怼一次大佬。
扫一遍,判断是否有\(C-f_j\le D-s_i\)即剩下的时间都还嘴。
注意\(f_j\)要\(\le C\)
三、怼两次大佬
不妨设怼的两次操作分别为\((f_a,s_a),(f_b,s_b)\)
则操作满足以下条件。
\(\huge \lbrace_{f_a+f_b\le C}^{C-f_a-f_b\le D-s_a-s_b}\)
实际上一式等价于\(C-f_a+s_a\le D+f_b-s_b\)
那么我们维护两个指针,指向\(a,b\)。
在保证\(f_a+f_b\le C\)的前提下,维护\(f_b-s_b\)的最大值。
就可以\(O(n)\)完成了。
/*
@Date : 2019-07-30 15:10:45
@Author : Adscn ([email protected])
@Link : https://www.cnblogs.com/LLCSBlog
*/
#include
using namespace std;
#define IL inline
#define RG register
#define gi getint()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
IL int getint()
{
RG int xi=0;
RG char ch=gc;
bool f=0;
while(ch<'0'||ch>'9')ch=='-'?f=1:f,ch=gc;
while(ch>='0'&&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;
return f?-xi:xi;
}
template
IL void pi(T k,char ch=0)
{
if(k<0)k=-k,putchar('-');
if(k>=10)pi(k/10,0);
putchar(k%10+'0');
if(ch)putchar(ch);
}
#define _d(i) all[i].second
#define _f(i) all[i].first
const int MAXN=117;
int f[MAXN][MAXN];
int n,m,mc,a[MAXN],w[MAXN],C[MAXN];
int mx;
int mxx;
#define mp(a,b) make_pair(a,b)
const int mod=19491001;
struct hashtable{
struct edge{
int x,y,nxt;
}e[1111111];
int head[mod+10],cnt;
hashtable(){memset(head,cnt=-1,sizeof head);}
inline int hash_func(int x,int y)
{
return (1ll*x*107+y)%mod+1;
}
inline void add(int x,int y){
int hashval=hash_func(x,y);
e[++cnt]=(edge){x,y,head[hashval]},head[hashval]=cnt;
}
bool find(int x,int y)
{
int hval=hash_func(x,y);
for(int i=head[hval];~i;i=e[i].nxt)
if(e[i].x==x&&e[i].y==y)
return 1;
return 0;
}
}ht;
struct node{int i,F,L;};
queueQ;
vector< pair >all;
signed main(void)
{
#ifndef ONLINE_JUDGE
File("file");
#endif
n=gi,m=gi,mc=gi;
for(int i=1;i<=n;++i)a[i]=gi;
for(int i=1;i<=n;++i)w[i]=gi;
for(int i=1;i<=m;++i)mx=max(mx,C[i]=gi);
for(int i=1;i<=n;++i)
for(int j=a[i];j<=mc;++j)
f[i][j-a[i]]=max(f[i-1][j]+1,f[i][j-a[i]]),
f[i][min(j-a[i]+w[i],mc)]=max(f[i-1][j],f[i][min(j-a[i]+w[i],mc)]);
for(int i=1;i<=n;++i)
for(int j=1;j<=mc;++j)
mxx=max(mxx,f[i][j]);
Q.push((node){1,1,0});
while(!Q.empty())
{
node u=Q.front();Q.pop();
if(u.i==mxx)continue;
Q.push((node){u.i+1,u.F,u.L+1});
if(u.L>1&&1ll*u.F*u.L<=1ll*mx&&!ht.find(u.F*u.L,u.i+1))
{
Q.push((node){u.i+1,u.F*u.L,u.L});
all.push_back(make_pair(u.F*u.L,u.i+1));
ht.add(u.F*u.L,u.i+1);
}
}
sort(all.begin(),all.end());
for(int i=1;i<=m;++i)
{
if(C[i]<=mxx){puts("1");continue;}
bool flag=0;
for(int j=all.size()-1,maxn=-1e9,k=0;j>=0;--j)
{
while(k=C[i]){flag=1;break;}
if(mxx+_f(j)-_d(j)+maxn>=C[i]){flag=1;break;}
}
cout<