这道题真的是跟我1314.。。。调了好久
思想:二分查找w,对于每一个枚举的w,都用数组pre[i] num[i]记录前i想满足条件的价值和、数量和。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=200000+10;
struct Node{
ll w,v;
}node[maxn];
int n,m;
ll S;
int part[2][maxn];
ll val[maxn];
int num[maxn];
ll f(int x)//如果x1和x2都满足
{
ll sum=0;
ll temp;
int i,j;
val[0]=num[0]=0;
for(i=1;i<=n;i++){
if(node[i].w>=x) val[i]=val[i-1]+node[i].v,num[i]=num[i-1]+1;
else val[i]=val[i-1],num[i]=num[i-1];
}
for(i=0;i<m;i++){
int l=part[0][i],r=part[1][i];
temp=(num[r]-num[l-1])*(val[r]-val[l-1]);
sum+=temp;
}
return sum-S;
}
int main()
{
int i,j,k;
cin >> n >> m >> S;
ll Max_W=0;
for(i=1;i<=n;i++){
scanf("%lld %lld",&node[i].w,&node[i].v);
Max_W=max(Max_W,node[i].w);
}
for(i=0;i<m;i++)
scanf("%d %d",&part[0][i],&part[1][i]);
int w1=0,w2=Max_W;
ll sum1=f(w1),sum2=f(w2);
while(w1<w2)
{
int mod=(w1+w2)>>1;
if(mod!=w1) sum2=f(mod);
else{
sum2=f(w2);
break;
}
if(0==sum1||0==sum2)
break;
else if(sum1<0&&sum2>0 || sum1>0&&sum2<0)
w2=mod;
else{
w1=mod;
sum1=sum2;
}
}
if(sum1<0) sum1=-sum1;
if(sum2<0) sum2=-sum2;
printf("%lld\n",(ll)min(sum1,sum2));
return 0;
}