其他分享
首页 > 其他分享> > AHOI/HNOI2017大佬

AHOI/HNOI2017大佬

作者:互联网



SOL:

首先可以发现保证自己不死和怼大佬是可以分开的

一个\(n^2DP\)算出最多可以用来怼大佬的天数,问题就转化为用\(n\)天怼大佬是否成功

先求出所有可能的讽刺值及其天数,惊人发现竟存的下!看来要多尝试才好

这样攻击一次和零次的都可以轻易判断

攻击两次(讽刺值\(f1,f2\)天数\(d1,d2\)):

\(f1+f2<=C,n-d1-d2>=C-f1-f2\)

可以排序后,用一个指针记录第二次攻击进行到哪了(根据第一个式子,单调性)

\((f1-d1)+(f2-d2)>=C-n\)

记录\(f2-d2\)的最大值即可

注:

搜索时判重,若同一层出现了一样的值则无效

按理说讽刺值一样是应是保留天数少的,但\(L\)不一定一样,我们必须让它搜下去,若直接搜要爆掉

这样判可以保证数的构造唯一,\(L\)唯一,不会漏,也不多

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f==1?x:-x;
}
#define ll long long
unordered_map<ll,bool>mp;
pair<int,int>dam[1111111];
#define fi(i) dam[i].first
#define se(i) dam[i].second 
struct node{int i,f,l;};
const int N=304;
int n,m,day,tot,mx,mc;
int a[N],w[N],c[N],g[N][N];
void bfs(){
    queue<node>q;
    q.push((node){1,1,0});
    while(!q.empty()){
        node u=q.front();q.pop();
        if(u.i==day)continue;
        q.push((node){u.i+1,u.f,u.l+1});
        if(u.l>1&&(ll)u.f*u.l<=mx&&!mp[(ll)u.f*u.l*100+u.i+1]){
            q.push((node){u.i+1,u.f*u.l,u.l});
            dam[++tot]=make_pair(u.f*u.l,u.i+1);
            mp[(ll)u.f*u.l*100+u.i+1]=1;
        }
    }
}
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++)mx=max(mx,c[i]=read());
    for(int i=1;i<=n;i++)
        for(int j=a[i];j<=mc;j++){
            g[i][j-a[i]]=max(g[i][j-a[i]],g[i-1][j]+1);
            g[i][min(mc,j-a[i]+w[i])]=max(g[i][min(mc,j-a[i]+w[i])],g[i-1][j]);
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=mc;j++)day=max(day,g[i][j]);
    bfs();
    sort(dam+1,dam+tot+1);
    for(int i=1,fl,mn;i<=m;i++){
        if(c[i]<=day){puts("1");continue;}
        fl=0;mn=1e9;
        for(int j=tot,k=1;j;j--){
            while(k<=tot&&fi(j)+fi(k)<=c[i]){
                mn=min(mn,se(k)-fi(k));
                ++k;
            }
            if(mn+c[i]-fi(j)<=day-se(j)){fl=1;break;}
            if(fi(j)<=c[i]&&c[i]-fi(j)<=day-se(j)){fl=1;break;}
        }
        if(fl==1)puts("1");
        else puts("0");
    }
    return (0-0);
}

标签:node,f1,f2,AHOI,int,天数,HNOI2017,大佬
来源: https://www.cnblogs.com/aurora2004/p/12523939.html