zoukankan      html  css  js  c++  java
  • P3724 [AH2017/HNOI2017]大佬

    传送门

    发现保持自信和做其他事情互不干扰,可以直接做一次 $dp$ 求出最多能空出几天来怼大佬

    然后就变成给你若干天,是否能怼死大佬,考虑求出所有的 天数和输出的嘲讽值集合,因为天数不多,嘲讽值增长很快

    所以直接 $BFS$ + $map$ 去重就行了

    不怼大佬或者只怼一次的情况容易计算,现在问题是怼两次的情况怎么搞

    设两次怼的嘲讽值分别为 $fx,fy$,输出这些嘲讽值需要的天数分别为 $dx,dy$

    如果要怼死大佬,只要满足限制 $fx+fy<=C$,$C-fx-fy<=D-dx-dy$,把刚刚得到的集合按 嘲讽值,天数 双关键字排序

    考虑维护两个指针 $x,y$,$x$ 从大到小,$y$ 从小到大,在枚举 $x$ 的时候移动 $y$ 使得 $y$ 满足 $fx+fy<=C$

    把第二个式子变一下 $C-fx<=D-dx+(fy-dy)$

    当我们固定了 $x$ 以后,要求的就是满足 $fx+fy<=C$ 中的 $fy-dy$ 的最大值

    因为随着 $fx$ 增加,之前枚举到的 $fy$ 一直满足条件,所以直接搞一个变量维护当前 $fy-dy$ 的最大值即可

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=207,M=1e7+7,INF=1e9+7;
    int n,m,mc,a[N],w[N],C[N];
    int f[N][N],D,tot,mx;
    struct dat{
        int d,f,l;
        dat (int a=0,int b=0,int c=0) { d=a,f=b,l=c; }
    };
    queue <dat> Q;
    struct datt{
        int f,d;
        datt (int a=0,int b=0) { f=a,d=b; }
        inline bool operator < (const datt &tmp) const {
            return f!=tmp.f ? f<tmp.f : d<tmp.d;
        }
    }T[M];
    map <datt,bool> vis;
    void BFS()
    {
        dat x=dat(1,1,0); Q.push(x);
        while(!Q.empty())
        {
            x=Q.front(); Q.pop(); if(x.d==D) continue;
            Q.push(dat(x.d+1,x.f,x.l+1));
            if(x.l>1&&1ll*x.f*x.l<=mx&&!vis[datt(x.f*x.l,x.d+1)])
            {
                Q.push((dat){x.d+1,x.f*x.l,x.l});
                T[++tot]=datt(x.f*x.l,x.d+1); vis[datt(x.f*x.l,x.d+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++) C[i]=read(),mx=max(mx,C[i]);
        for(int i=1;i<=n;i++)
            for(int j=a[i];j<=mc;j++)
            {
                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][min(j-a[i]+w[i],mc)],f[i-1][j]);
            }
        for(int i=1;i<=n;i++)
            for(int j=0;j<=mc;j++) D=max(D,f[i][j]);
        BFS(); sort(T+1,T+tot+1);
        for(int i=1;i<=m;i++)
        {
            if(C[i]<=D) { printf("1
    "); continue; }
            bool flag=0; int GG=-INF;
            for(int x=tot,y=1;x;x--)
            {
                while(y<=tot && T[x].f+T[y].f<=C[i]) GG=max(GG,T[y].f-T[y].d),y++;
                if( y<=tot && C[i]-T[x].f<=D-T[x].d+GG ) { flag=1; break; }
                if(T[x].f<=C[i] && C[i]-T[x].f<=D-T[x].d) { flag=1; break; }
            }
            printf("%d
    ",flag);
        }
        return 0;
    }
  • 相关阅读:
    time zone list
    docker build doris-0.11.20-release source code
    Apache Flink 开发环境搭建和应用的配置、部署及运行
    locate home of running java application
    Android wpa_supplicant 四次握手 流程分析
    Wifi 开放系统认证和共享密钥身份认证
    Android WiFi 获取国家码
    Android WiFi 扫描流程分析(wpa_supplicant选择网络)
    Android WiFi 日志记录(ASSOC_REJECT)
    Android WiFi 扫描流程分析(wpa_supplicant)
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11387996.html
Copyright © 2011-2022 走看看