zoukankan      html  css  js  c++  java
  • [CTSC2018]混合果汁(二分答案+主席树)

    考场上写了60分的二分答案,又写了15分的主席树,然后就弃了。。

    合起来就A了啊!主席树忘了开20倍空间最后还炸掉了。

    最水的签到题被我扔了,主要还是不会用线段树求前缀和。

    做法应该是比较显然的,首先肯定要二分答案,然后需要查询的就是大于等于当前二分值的最便宜的L个饮料的总花费是否不超过g,这个直接上主席树就好。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define rep(i,l,r) for (int i=l; i<=r; i++)
     4 typedef long long ll;
     5 using namespace std;
     6 
     7 const int N=100010,M=1800010,Mx=100000;
     8 struct P{ int d,p,l; }a[N];
     9 bool cmp(const P &a,const P &b){ return a.d<b.d; }
    10 int n,m,nd,tot,b[N],ls[M],rs[M],root[N];
    11 ll g,q,c[N],sz[M],sm[M];
    12 
    13 void ins(int y,int &x,int L,int R,int pos,int k){
    14     x=++nd; ls[x]=ls[y]; rs[x]=rs[y]; sz[x]=sz[y]; sm[x]=sm[y];
    15     if (L==R){ sz[x]+=k; sm[x]+=1ll*L*k; return; }
    16     int mid=(L+R)>>1;
    17     if (pos<=mid) ins(ls[y],ls[x],L,mid,pos,k);
    18         else ins(rs[y],rs[x],mid+1,R,pos,k);
    19     sz[x]=sz[ls[x]]+sz[rs[x]]; sm[x]=sm[ls[x]]+sm[rs[x]];
    20 }
    21 
    22 ll que(int x,int L,int R,ll pos){
    23     if (L==R) return L*pos;
    24     int mid=(L+R)>>1;
    25     if (sz[ls[x]]>=pos) return que(ls[x],L,mid,pos);
    26         else return sm[ls[x]]+que(rs[x],mid+1,R,pos-sz[ls[x]]);
    27 }
    28 
    29 bool jud(int mid){
    30     if (c[tot]-c[mid-1]<q) return 0;
    31     return que(root[mid],1,Mx,q)<=g;
    32 }
    33 
    34 int main(){
    35     freopen("juice.in","r",stdin);
    36     freopen("juice.out","w",stdout);
    37     scanf("%d%d",&n,&m);
    38     rep(i,1,n) scanf("%d%d%d",&a[i].d,&a[i].p,&a[i].l),b[++tot]=a[i].d;
    39     sort(b+1,b+tot+1); tot=unique(b+1,b+tot+1)-b-1; b[0]=-1;
    40     rep(i,1,n) a[i].d=lower_bound(b+1,b+tot+1,a[i].d)-b,c[a[i].d]+=a[i].l;
    41     rep(i,2,tot) c[i]+=c[i-1];
    42     sort(a+1,a+n+1,cmp); int j=n;
    43     for (int i=tot; i; i--){
    44         root[i]=root[i+1];
    45         for (; j && a[j].d>=i; j--) ins(root[i],root[i],1,Mx,a[j].p,a[j].l);
    46     }
    47     rep(i,1,m){
    48         scanf("%lld%lld",&g,&q);
    49         int l=1,r=tot,ans=0;
    50         while (l<=r){
    51             int mid=(l+r)>>1;
    52             if (jud(mid)) ans=mid,l=mid+1; else r=mid-1;
    53         }
    54         printf("%d
    ",b[ans]);
    55     }
    56     return 0;
    57 }
  • 相关阅读:
    【个人博客设计】
    复杂多边形光栅化算法
    xmake 描述语法和作用域详解
    协程分析之context上下文切换
    tbox协程使用之切换与等待
    记boost协程切换bug发现和分析
    跨平台自动构建工具v1.0.2 发布
    xmake从入门到精通9:交叉编译详解
    xmake从入门到精通9:交叉编译详解
    跨平台c开发库tbox:内存库使用详解
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9046588.html
Copyright © 2011-2022 走看看