3 条题解
-
0
(蒟蒻的刚写好的题解被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
- 上传者