[CTSC2018]混合果汁(二分答案+主席树)

摘要:
考场写了60分的两分答案和15分的总统树,然后放弃了!主席树忘记打开20倍的空间,最后把它炸了。我抛出了最有争议的符号,主要是因为我无法使用线段树来查找前缀和。这种做法应该是显而易见的。首先,答案必须分为两部分。然后,您需要查询的是,最便宜的L饮料的总成本是否大于或等于当前的两点值,是否不超过g。直接转到董事长树是很好的。

考场上写了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 }

免责声明:文章转载自《[CTSC2018]混合果汁(二分答案+主席树)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇[BZOJ1790][AHOI2008]Rectangle 矩形藏宝地(四维偏序,CDQ+线段树)[BZOJ3944]Sum(杜教筛)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

主席树小结

https://zybuluo.com/ysner/note/1099145 标签(空格分隔): 主席树 前置技能 线段树 动态开点 标记永久化 离散化 定义 主席树=可持久化线段树=函数式线段树线段树经过了若干次修改之后,仍然能找到原来某次修改前的线段树的信息的一种数据结构 建立 据说最无脑的方法是每修改一次新建一颗主席树??? 单点修改: 线段树...

【线段树】树套树 树状数组套主席树

树状数组套主席树 (其实是树状数组套动态开点权值线段树 作用: 即动态主席树,动态(带修)查询区间 (k) 小(大)值 做法: 回顾主席树:简单来说主席树在查询时 是查询 (T[r]-T[l-1]) 区间的值的,建立是 (T[i+1]) 在 (T[i]) 的基础上建立的。用于静态查询区间 (k) 小(大)值。 而带修主席树,因为修改,所以在 (T[i]) 基...

poj2104 主席树模板题

题意 给出n个数字组成的数字序列,有m组询问。每次询问包含三个数字l,r,k。对于每个询问输出序列区间[l,r]中第k大的数字。 分析 这是主席树的模板题,套板子就可以 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include...

【BZOJ5319】【JSOI2018】—军训列队(主席树)

传送门 显然是直接按照位置来排队最优考虑每次是把编号一段拿出来,考虑建一颗主席树可以在主席树上二分找到在kkk前的人要站到哪儿注意有可能二分到的位置可能还是被放到特判+1即可然后随便算一下就可以了 #include<bits/stdc++.h> using namespace std; #define ll long long inline in...

浅谈数据结构之主席树(线段树进阶版)

今天看了点主席树的概念,加上飞哥上次讲的,目前对主席树有了大致的了解,简单谈谈吧,不讲代码,只讲思路,日后贴题! Orz高级数据结构发明者主席!!最早在CLJ的课件里第一次看到了这个词,最近做区间第K大时又想起了这茬,这方面资料也挺少的,于是再次膜拜下主席,对主席树理解有不到位的地方也欢迎指正。 然后读以下文字时最好有些线段树的预备知识,毕竟根据发明...

BZOJ 4012 [HNOI2015]开店 (区间修改 永久化标记 主席树)

讲得好啊主席树区间修改了,每一次遇到整区间就打永久化标记(不下传,访问的时候沿路径上的标记算答案)然后returnreturnreturn,那么每修改一次只会访问到lognlognlogn个节点,再加上每个点要在树链上修改lognlognlogn次,所以空间复杂度O(nlog2n)O(nlog^2n)O(nlog2n),实测开O(n∗50)O(n*50)O(...