BZOJ 4828: [AH2017/HNOI2017]大佬 Dp
作者:互联网
title
题面巨长,再次不想贴了
analysis
细读题面,可以发现和自己自信值有关的就一项,所以题目再三强调的你不能死,其实是句废话。
但是最终答案是问是否能怼死大佬,而跟着有关的就天数和嘲讽值这两个因素,所以,好像清晰了点儿(但是好像还是改变不了这是个神仙题的事实)。
下面就把可行的天数,嘲讽值都求出来,然后再把嘲讽值从小到大排个序(当然,这两个用个 \(pair\) 连起来,不是让分开搞的)。
不怼,或者怼一次就把大佬怼死了(这还是大佬吗)的情况比较容易判断,所以...
那么问题就是怼两次怼死他的情况:
然后,我就...不会了...
下面就是看过 yyb \(blog\) 后才会的。
不妨设两次怼大佬花费的天数分别是 \(d_1,d_2\) ,总共可以怼 \(D\) 天,嘲讽值分别是 \(f_1,f_2\) 。
我们可以列出不等式:
\[
f_1+f_2<=C,f_1+f_2+(D−d_1−d_2)>=C
\]
考虑按照 \(f\) 为第一关键字, \(d\) 为第二关键字排序,
现在维护两个指针,分别从大往小和从小往大枚举,每次保证 \(f_i+f_j<=C\) 。
因为我们固定了一个方向,不妨固定了 \(f_i\) 所以,此时的定值是 \(f_i,d_i,D,C\) ,
那么,这个时候要求的就是 \(f_2−d_2\) 的最大值
在从小到大扫的过程中,显然是单调的,因此不需要再从头开始扫,直接继承上一次的指针位置继续向后即可。
code
#include<bits/stdc++.h>
#define mp std::make_pair
typedef std::pair<int,int> pii;
const int maxn=111,mod=1000007;
namespace IO
{
char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
char Out[1<<24],*fe=Out;
inline void flush() { fwrite(Out,1,fe-Out,stdout); fe=Out; }
template<typename T>inline void write(T x,char str)
{
if (!x) *fe++=48;
if (x<0) *fe++='-', x=-x;
T num=0, ch[20];
while (x) ch[++num]=x%10+48, x/=10;
while (num) *fe++=ch[num--];
*fe++=str;
}
}
using IO::read;
using IO::write;
template<typename T>inline bool chkMin(T &a,const T &b) { return a>b ? (a=b, true) : false; }
template<typename T>inline bool chkMax(T &a,const T &b) { return a<b ? (a=b, true) : false; }
template<typename T>inline T min(T a,T b) { return a<b ? a : b; }
template<typename T>inline T max(T a,T b) { return a>b ? a : b; }
struct Hash_Table
{
int spot[mod+3],ver[mod+3],Next[mod+3],head[mod+1],len;
inline void add(int x,int y)
{
int pos=(1ll*x*101+y)%mod;
spot[++len]=x,ver[len]=y,Next[len]=head[pos],head[pos]=len;
}
inline bool query(int x,int y)
{
int pos=(1ll*x*101+y)%mod;
for (int i=head[pos]; i; i=Next[i])
if (spot[i]==x && ver[i]==y) return true;
return false;
}
} M;
pii o[mod+3];
struct Orz{int i,F,L;};
int tot,mx,Day;
inline void bfs()
{
std::queue<Orz>q;
q.push((Orz){1,1,0});
while (!q.empty())
{
Orz x=q.front();
q.pop();
if (x.i==Day) continue;
q.push((Orz){x.i+1,x.F,x.L+1});
if (x.L>1 && 1ll*x.L*x.F<=1ll*mx && !M.query(x.F*x.L,x.i+1))
{
q.push((Orz){x.i+1,x.F*x.L,x.L});
o[++tot]=mp(x.F*x.L,x.i+1);
M.add(x.F*x.L,x.i+1);
}
}
}
int a[maxn],w[maxn],c[maxn],f[maxn][maxn];
int main()
{
int n,m,mc;
read(n);read(m);read(mc);
for (int i=1; i<=n; ++i) read(a[i]);
for (int i=1; i<=n; ++i) read(w[i]);
for (int i=1; i<=m; ++i) read(c[i]),chkMax(mx,c[i]);
for (int i=1; i<=n; ++i)
for (int j=a[i]; j<=mc; ++j)
{
chkMax(f[i][j-a[i]],f[i-1][j]+1);
chkMax(f[i][min(j-a[i]+w[i],mc)],f[i-1][j]);
}
for (int i=1; i<=n; ++i)
for (int j=1; j<=mc; ++j) chkMax(Day,f[i][j]);
bfs();
std::sort(o+1,o+tot+1);
for (int i=1; i<=m; ++i)
{
if (c[i]<=Day) { write(1,'\n'); continue; }
int flag=0, mn=1e9;
for (int j=tot, k=1; j; --j)
{
while (k<tot && o[k].first+o[j].first<=c[i]) chkMin(mn,o[k].second-o[k].first), ++k;
if (mn+c[i]-o[j].first<=Day-o[j].second) { flag=1; break; }
if (o[j].first<=c[i] && c[i]-o[j].first<=Day-o[j].second) { flag=1; break; }
}
write(flag,'\n');
}
IO::flush();
return 0;
}
标签:ch,return,4828,int,pos,len,AH2017,HNOI2017,mod 来源: https://www.cnblogs.com/G-hsm/p/11455917.html