• [CTSC2018]混合果汁


    V.III.[CTSC2018]混合果汁

    二话不说先套个整体二分。

    但是这题整体二分与先前两道题有所区别——前面两道题,当二分到区间 \([l,r]\) 时,只需管 \([l,r]\) 中的元素就行了,对于 \(mid\) 不合法的询问直接减去这一段的询问的结果就行了;

    但是,本题就不一样了:随着美味度下界的不断降低,我们可能会放弃贵但美味的饮料,转而选择便宜但不美味的饮料。这就意味着上面的做法不太行。

    但是,我们是有办法的:仿照CDQ分治的思想,当处理区间 \([l,r]\) 结束后,我们首先处理 \([mid,r]\),等到遍历到叶子节点时将其代表的元素加入BIT,等 \([mid,r]\) 全数处理完成后再处理 \([l,mid]\)。这样子,在处理任何 \([l,r]\) 时,\([r+1,n]\) 便已经在BIT里了。

    至于这个BIT是用来干嘛的呢,你可以在上面二分出要买几升果汁最少花多少钱。

    时间复杂度 \(O(n\log^2n)\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1<<17;
    int n,m,p[N+10],res[N+10];
    ll mon[N+10],wat[N+10],lit[N+10],pay[N+10],all;
    bool ok[N+10];
    vector<pair<int,int> >v[N+10];
    void ADD(int pri,int amt){all+=amt;for(int i=pri;i<=N;i+=i&-i)lit[i]+=amt,pay[i]+=1ll*pri*amt;}//price,amount
    ll ASK(ll amt){
    	int i=N;ll cst=0;
    //	printf("%lld:\n",amt);
    	for(int j=17;j>=0;j--){
    		if(i<(1<<j))continue;
    //		printf("%d:%d %d:%d,%d %d\n",i,j,i-(1<<j),lit[i-(1<<j)],pay[i-(1<<j)],amt);
    		if(lit[i-(1<<j)]>=amt)i-=(1<<j);else amt-=lit[i-(1<<j)],cst+=pay[i-(1<<j)];
    	}
    	cst+=i*amt;
    //	printf("%lld,%d,%lld\n",amt,i,cst);
    	return cst;
    }
    void solve(int l,int r,int L,int R){
    	if(l==r){
    //		printf("[%d]:",l);for(int i=L;i<=R;i++)printf("%d ",p[i]);puts("");
    		for(int i=L;i<=R;i++)res[p[i]]=l;
    		for(auto i:v[l])ADD(i.first,i.second);
    		return;
    	}
    	int mid=(l+r+1)>>1;
    	for(int i=mid;i<=r;i++)for(auto j:v[i])ADD(j.first,j.second);
    //	printf("%lld:[%d|%d|%d]:",all,l,mid,r);for(int i=L;i<=R;i++)printf("%d ",p[i]);puts("");
    	for(int i=L;i<=R;i++)ok[p[i]]=(all>=wat[p[i]]&&ASK(wat[p[i]])<=mon[p[i]]);
    	for(int i=mid;i<=r;i++)for(auto j:v[i])ADD(j.first,-j.second);
    	sort(p+L,p+R+1,[](int x,int y){return ok[x]>ok[y];});
    	int MID=L-1;while(MID<R&&ok[p[MID+1]])MID++;
    	solve(mid,r,L,MID),solve(l,mid-1,MID+1,R);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1,x,y,z;i<=n;i++)scanf("%d%d%d",&x,&y,&z),v[x].push_back(make_pair(y,z));
    	for(int i=1;i<=m;i++)scanf("%lld%lld",&mon[i],&wat[i]),p[i]=i;
    	solve(0,N,1,m);
    	for(int i=1;i<=m;i++)printf("%d\n",!res[i]?-1:res[i]);
    	return 0;
    }
    
  • 相关阅读:
    扫描线算法模板
    spark submit 常用设置
    networkx 画有向图 使用DiGraph
    超实用的Spark数据倾斜解决
    解决spark中遇到的数据倾斜问题
    TrickBot 恶意木马软件
    windows 打开snappy文件 安装python snappy——还是直接用pip install xx.whl 打包好的安装吧
    解决CentOS删除文件后没有释放磁盘空间(lsof命令)
    Linux 系统下 centOS 7 ipconfig 提示没有安装
    tomcat启动报错org.apache.catalina.LifecycleException: The configured protocol [org.apache.coyote.http...
  • 原文地址:https://www.cnblogs.com/Troverld/p/14620869.html
Copyright © 2020-2023  润新知