• [CTSC2018]混合果汁


    前言

    先写思路后码代码,应该是对的,等我写完验证一下就知道了。

    update 2021.4.6 写完了,一遍过。

    题目

    洛谷

    讲解

    我们先思考这样一个事情:如果规定一些果汁可以选,那么我们显然可以贪心选这些果汁中单价最少的判断是否可以满足一个小朋友的要求。

    当然我们也可以将其放到线段树上,以价格为下标,查询的时候可以在线段树上二分。

    显然我们要二分果汁美味度,以标记可以选的果汁有哪些,我们显然不能重新建树,为了保证时间复杂度,我们用主席树来动态维护前缀和。

    多个小朋友?整体二分即可(似乎不用整体二分而直接做 (m) 次二分也行,只是常数稍微大了一点点)。

    每个孩子在二分时最多会在主席树上查询 (log_2n) 次,时间复杂度应该是 (O(nlog_2^2n)) 级别。

    代码

    小常数!

    struct Juice
    {
    	int d,p,l;//美味度 单价 上限 
    	bool operator < (const Juice &px)const{
    		return d < px.d;
    	}
    }s[MAXN];
    struct Children
    {
    	LL g,L;
    	int ID;
    }c[MAXN],c2[MAXN];
    int rt[MAXN];
    struct PresidentTree
    {
    	int tot;
    	struct node
    	{
    		int ch[2];
    		LL P,V;//总价钱  总体积 
    	}t[MAXN * 30];
    	
    	void Add(int lst,int &now,int l,int r,Juice ad)
    	{
    		now = ++tot;
    		t[now] = t[lst];
    		t[now].P += 1ll * ad.p * ad.l; 
    		t[now].V += ad.l;
    		if(l == r) return;
    		int mid = (l+r) >> 1;
    		if(ad.p <= mid) Add(t[lst].ch[0],t[now].ch[0],l,mid,ad);
    		else Add(t[lst].ch[1],t[now].ch[1],mid+1,r,ad);
    	}
    	
    	bool Query(int lst,int now,int l,int r,Children A)
    	{
    		if(t[now].V - t[lst].V < A.L) return 0;
    		if(t[now].V - t[lst].V >= A.L && A.g >= t[now].P - t[lst].P) return 1;
    		if(l == r) return A.g / l >= A.L;
    		int mid = (l+r) >> 1;
    		if(t[t[now].ch[0]].V - t[t[lst].ch[0]].V >= A.L) return Query(t[lst].ch[0],t[now].ch[0],l,mid,A);
    		else if(t[t[now].ch[0]].P - t[t[lst].ch[0]].P > A.g) return 0;
    		else 
    		{
    			A.g -= t[t[now].ch[0]].P - t[t[lst].ch[0]].P;
    			A.L -= t[t[now].ch[0]].V - t[t[lst].ch[0]].V;
    			return Query(t[lst].ch[1],t[now].ch[1],mid+1,r,A);
    		}
    	}
    }pt;
    
    void solve(int l,int r,int cl,int cr)
    {
    	int mid = (l+r) >> 1;
    	int tot1 = cl,tot2 = 0;
    	for(int i = cl;i <= cr;++ i)
    	{
    		if(pt.Query(rt[ef[mid]-1],rt[n],1,MAX,c[i])) ans[c[i].ID] = s[ef[mid]].d,c2[++tot2] = c[i];
    		else c[tot1++] = c[i];
    	}
    	if(l == r) return;
    	for(int i = 1;i <= tot2;++ i) c[tot1+i-1] = c2[i];
    	solve(l,mid,cl,tot1-1); solve(mid+1,r,tot1,cr);
    }
    
    int main()
    {
    
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read(); m = Read();
    	for(int i = 1;i <= n;++ i) s[i].d = Read(),s[i].p = Read(),s[i].l = Read(),MAX = Max(MAX,s[i].p);
    	for(int i = 1;i <= m;++ i) c[i].g = Read(),c[i].L = Read(),c[i].ID = i;
    	sort(s+1,s+n+1);
    	for(int i = 1;i <= n;++ i) 
    	{
    		pt.Add(rt[i-1],rt[i],1,MAX,s[i]);
    		if(s[i].d != s[i-1].d) ef[++nn] = i;
    	}
    	solve(1,nn,1,m);
    	for(int i = 1;i <= m;++ i) Put(ans[i] ? ans[i] : -1,'
    ');
    	return 0;
    }
    

    后记

    目前洛谷rk1。

  • 相关阅读:
    TreeSet类的排序问题
    TreeSet()详解
    css中vertical-align垂直居中的认识
    CSS3 float深入理解浮动资料整理
    层叠顺序与层叠上下文
    jquery.zclip轻量级复制失效问题
    文章转载利用border、transparent实现微风
    转载利用线性渐变实现晴天、多云特效
    转载利用伪元素单个颜色实现 hover 和 active 时的明暗变化效果
    MUI-最接近原生App体验的前端框架
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/14514687.html
Copyright © 2020-2023  润新知