[CTSC2018]混合果汁

考虑二分答案+可持久化线段树。

对于这种最大化最小值的问题,通常使用二分来解决。于是我们想到了对果汁按其d值排序。然后使用下标为费用的一棵可持久化线段树来维护费用。

check函数可以这样写:如果我们发现以mid为根的线段树本身还不够li升,就可以直接返回0了,否则贪心地查询其最小花费,如果也符合要求,那么就返回1

于是这题就是这样:先对果汁按美味度排序,然后按单价丢进一棵主席树中,最后对于询问,二分答案并贪心验证。

这真是一道比较水的CTSC

参考代码如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring> 
 4 #include<algorithm>
 5 #define int long long
 6 #define N 200005
 7 using namespace std;
 8 int read()
 9 {
10     int x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
13     return x*f;
14 }
15 struct node{int d,p,l;}juice[N];
16 struct hjt_tree{int ls,rs,w,l;}t[N*21];
17 bool cmp(node a,node b){if(a.d!=b.d)return a.d<b.d;return a.p<b.p;}
18 int n,m,T[N],MAXP,cnt,limg,liml;
19 void modify(int &node,int last,int l,int r,int x,int ll,int ww)
20 {
21     node=++cnt;t[node]=t[last];t[node].l+=ll,t[node].w+=ww;
22     if(l==r)return;
23     int mid=(l+r)>>1;
24     if(x<=mid)modify(t[node].ls,t[last].ls,l,mid,x,ll,ww);
25     else modify(t[node].rs,t[last].rs,mid+1,r,x,ll,ww);
26 }
27 int query(int node,int l,int r,int w)
28 {
29     if(l==r)return w*l;
30     int mid=(l+r)>>1;
31     if(t[t[node].ls].l>=w)return query(t[node].ls,l,mid,w);
32     else return t[t[node].ls].w+query(t[node].rs,mid+1,r,w-t[t[node].ls].l);
33 }
34 bool check(int mid)
35 {
36     if(liml>limg)return 0;
37     if(t[T[mid]].l>=liml&&query(T[mid],1,MAXP,liml)<=limg)return 1;
38     return 0; 
39 }
40 signed main()
41 {
42     n=read();m=read();
43     for(int i=1;i<=n;i++)
44     {
45         juice[i].d=read();juice[i].p=read();juice[i].l=read();
46         //MAXP=max(MAXP,juice[i].p);
47     }
48     MAXP=200001;
49     sort(juice+1,juice+1+n,cmp);
50     for(int i=n;i>=1;i--)modify(T[i],T[i+1],1,MAXP,juice[i].p,juice[i].l,juice[i].p*juice[i].l);
51     while(m--)
52     {
53         limg=read();liml=read();
54         int ans=-1,ll=1,rr=n,mid;
55         while(ll<=rr)
56         {
57             mid=(ll+rr)>>1;
58             if(check(mid))ll=mid+1,ans=mid;
59             else rr=mid-1;
60         }
61         if(ans==-1)printf("-1\n");
62         else printf("%d\n",juice[ans].d);
63     }
64     return 0;
65 }
[CTSC2018]混合果汁

 

posted @ 2019-09-09 22:59  shao0320  阅读(223)  评论(0编辑  收藏  举报
****************************************** 页脚Html代码 ******************************************