3 条题解

  • 0
    @ 2026-9-21 11:45:57

    (蒟蒻的刚写好的题解被syoj吃掉了QwQ,为什么就退登了啊QwQ,我写好的题解!) 只能再写一遍了 核心思路 本题要求选择一个阈值W(后面才反应过来是p,见谅一下)使得所有查询区间内满足vi>=W的物品的「个数×权值和」之和 q 尽可能接近目标值 T。 关键性质在于单调性:当阈值 W 增大时,符合条件的物品单调不增,所以果断二分(不过我在考场上犯傻了忘了),然后最优解一定出现在从>=T变为<T的临界点附近 至于如何计算q,使用神秘的前缀和预处理加每个区间计算可以O(n+m)解决,加上二分就是O((n+m)logn)QAQ 注意事项: (本来写的很多结果被吃了,没时间了)就是不一定一定是l是最终结果,l-1,l,l+1都可能,注意一下 附上代码

    #include<bits/stdc++.h>
    #define lhhsyn ios::sync_with_stdio(false)
    #define fc cin.tie(0)
    using namespace std;
    typedef long long ll;
    const int N=200005;
    int n,m;
    ll t;
    int v[N],w[N],tmp[N];
    int a[N],b[N];
    ll sum[N],cnt[N],q,res=1e18,l,r,mid;
    void qzh(ll p){
    	for(int i=1;i<=n;i++){
    		cnt[i]=cnt[i-1];
    		sum[i]=sum[i-1];
    		if(v[i]>=p){
    			cnt[i]+=1;
    			sum[i]+=w[i];
    		}
    	}
    }
    ll solve(ll p){
    	qzh(p);
    	q=0;
    	for(int j=1;j<=m;j++){
    		q+=(sum[b[j]]-sum[a[j]-1])*(cnt[b[j]]-cnt[a[j]-1]);
    	}
    	return q;
    }
    int main(){
    	lhhsyn;
    	fc;
    	cin>>n>>m>>t;
    	for(int i=1;i<=n;i++){
    		cin>>v[i]>>w[i];
    		tmp[i]=v[i];
    	}
    //这何尝不是离散化
    	sort(tmp+1,tmp+n+1);
    	for(int i=1;i<=m;i++){
    		cin>>a[i]>>b[i];
    	}
    	l=1,r=n;
    	while(l<r){
    		mid=(l+r+1)/2;
    		if(solve(tmp[mid])>=t)l=mid;
    		else r=mid-1;
    	}
    	for(int i=l-1;i<=l+1;i++){//注意边界,我这里懒得写了,反正A了,不过这是不好的习惯,不要学
    		res=min(res,abs(solve(tmp[i])-t));
    	} 
    	cout<<res;
    	return 0;
    }
    
    

    信息

    ID
    40
    时间
    1000ms
    内存
    256MiB
    难度
    6
    标签
    (无)
    递交数
    74
    已通过
    22
    上传者