• [BZOJ1701] [Usaco2007 Jan]Cow School牛学校


    [BZOJ1701] [Usaco2007 Jan]Cow School牛学校

    可以说是一道变异的01规划

    其实就是问是否存在方案满足不是选\(t/p\)最高的最优

    设当前选了这些点,总答案是\(s\),即\(\sum t_i-p_i*s = 0\)

    如果存在方案,则必然满足存在集合S \(\sum_{i \in S}t_i-p_i*s>0\)

    然而,其实只要把选了的点中\(t_i-p_i*s\)最小的换成没选的中\(t_i-p_is\)中最大的,看看是否大于0即可

    所以可以用斜率优化求最值,由于查询不具有单调性,所以要用 分治+单调栈+二分

    两边求解后统计答案即可

    const int N=5e4+10,P=1e9+7;
    
    int n;
    struct Node{ 
        int a,b;
        bool operator < (const Node __)const{ return 1.0*a/b>1.0*__.a/__.b; }
    }A[N],B[N];
    bool cmp(Node a,Node b){
        return a.a<b.a;
    }
     
    double sa[N],sb[N];
    double res[N];
    double ma[N],mi[N];
    double QA[N],QB[N];
    int L,R;
     
    void Solve1(int l,int r) {
        if(l>=r) return;
        int mid=(l+r)>>1;
        rep(i,l,mid) B[i]=(Node){A[i].b,A[i].a};
        sort(B+l,B+mid+1,cmp);
        L=1,R=0;
        rep(i,l,mid) {
            while(L<R && (QB[R]-QB[R-1])/(QA[R]-QA[R-1])>(B[i].b-QB[R])/(B[i].a-QA[R]) ) R--;
            QB[++R]=B[i].b;
            QA[R]=B[i].a;
        }
        rep(i,mid+1,r) {
            double t=res[i-1];
            int bl=2,br=R,bmid,bres=1;
            while(bl<=br) {
                bmid=(bl+br)>>1;
                if((QB[bmid]-QB[bmid-1])/(QA[bmid]-QA[bmid-1])<=t) bl=bmid+1,bres=bmid;
                else br=bmid-1;
            }
            mi[i-1]=min(mi[i-1],QB[bres]-t*QA[bres]);
        }
        Solve1(l,mid);
        Solve1(mid+1,r);
    }
     
    void Solve2(int l,int r) {
        if(l>=r) return;
        int mid=(l+r)>>1;
        rep(i,mid+1,r) B[i]=(Node){A[i].b,A[i].a};
        sort(B+mid+1,B+r+1,cmp);
        L=1,R=0;
        rep(i,mid+1,r) {
            while(L<R && (QB[R]-QB[R-1])/(QA[R]-QA[R-1])<(B[i].b-QB[R])/(B[i].a-QA[R]) ) R--;
            QB[++R]=B[i].b;
            QA[R]=B[i].a;
        }
        rep(i,l,mid) {
            double t=res[i];
            int bl=2,br=R,bmid,bres=1;
            while(bl<=br) {
                bmid=(bl+br)>>1;
                if((QB[bmid]-QB[bmid-1])/(QA[bmid]-QA[bmid-1])>=t) bl=bmid+1,bres=bmid;
                else br=bmid-1;
            }
            ma[i]=max(ma[i],QB[bres]-t*QA[bres]);
        }
        Solve2(l,mid);
        Solve2(mid+1,r);
    }
    int cnt;
     
    int main(){
        rep(i,1,n=rd()) A[i].a=rd(),A[i].b=rd();
        sort(A+1,A+n+1);
        rep(i,1,n) {
            sa[i]=sa[i-1]+A[i].a,sb[i]=sb[i-1]+A[i].b;
            ma[i]=-1e18;
            mi[i]=1e18;
        }
        rep(i,1,n) res[i]=sa[i]/sb[i];
        Solve1(1,n+1);
        Solve2(1,n);
        drep(i,n-1,1) if(ma[i]>mi[i]) cnt++;
        printf("%d\n",cnt);
        drep(i,n-1,1) if(ma[i]>mi[i]) printf("%d\n",n-i);
    }
     
     
    
  • 相关阅读:
    最大子串和
    [USACO1.5]数字金字塔 Number Triangles
    数字金字塔
    台阶问题
    取余运算
    数列分段pascal程序
    Java 集合-Collection接口和迭代器的实现
    Java 集合-集合介绍
    Java IO流-File类
    Git学习记录
  • 原文地址:https://www.cnblogs.com/chasedeath/p/11743206.html
Copyright © 2020-2023  润新知