题解 P1314 【聪明的质监员】
这道题可以看出来是一道二分题(没错一下就看出来了),因为你的Y随着变量w的变化时有序的,即w递增时Y递减。
while(wn<=wx){
int mid=(wn+wx)>>1;
if(check(mid)){
wn=mid+1;
}
else{
wx=mid-1;
}
ans=min(ans,abs(Y-S));
}
然后再结合前缀和的技巧就能减少求和的时间
for(int i=1;i<=n;i++){
sumv[i]=sumv[i-1];
sumn[i]=sumn[i-1];
if(w[i]>=wm){
sumv[i]+=v[i];
sumn[i]+=1;
}
}
注意数据大小,使用long long 下面是总代码
#include<stdio.h>
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
long long m,n,S,Y;
int w[200010],v[200010];
vector<int> ww;
int st;
int lt[200010],rt[200010];
long long sumn[200010],sumv[200010];
int wn=100000000,wx=0;
bool check(int wm){
Y=0;
memset(sumv,0,sizeof(sumv));
memset(sumn,0,sizeof(sumn));
for(int i=1;i<=n;i++){
sumv[i]=sumv[i-1];
sumn[i]=sumn[i-1];
if(w[i]>=wm){
sumv[i]+=v[i];
sumn[i]+=1;
}
}
for(int i=1;i<=m;i++){
long long sum;
sum=(sumv[rt[i]]-sumv[lt[i]-1])*(sumn[rt[i]]-sumn[lt[i]-1]);
Y+=sum;
}
if(Y>S) return true;
else return false;
}
int main(){
cin>>n>>m>>S;
for(int i=1;i<=n;i++){
scanf("%d%d",&w[i],&v[i]);
wn=min(wn,w[i]);
wx=max(wx,w[i]);
}
for(int i=1;i<=m;i++){
scanf("%d%d",<[i],&rt[i]);
}
long long ans=0x7fffffffffff;
while(wn<=wx){
int mid=(wn+wx)>>1;
if(check(mid)){
wn=mid+1;
}
else{
wx=mid-1;
}
ans=min(ans,abs(Y-S));
}
cout<<ans;
return 0;
}