输入样例:
5 3 15
1 5
2 5
3 5
4 5
5 5
1 5
2 4
3 3
输出样例:
10
这道题说实话并不是很难,我刚开始也是想到了二分,但是那个式子确实让我看的一脸懵逼 。
后来在老师的代码中才知道,Yi是在Li,Ri区间中求符合wi>=W的个数*符合wi>=W的总价值。求Y与S的最小绝对值。
思路就比较好求了,类似于求lower_bound的二分,可以求>=S的最大W,也可以求<=S的最小W
然后S两边都有可能是绝对值最小,思路就出来了
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int N=2e5+10;
int wi[N],vi[N],li[N],Ri[N],cot[N];
int n,m;
LL s[N],S;
LL check(int W)
{
for(int i=1;i<=n;i++)
if(wi[i]>=W)
{
s[i]=s[i-1]+vi[i];
cot[i]=cot[i-1]+1;
}
else
{
s[i]=s[i-1];
cot[i]=cot[i-1];
}
LL res=0;
for(int i=1;i<=m;i++) res+=(cot[Ri[i]]-cot[li[i]-1])*(s[Ri[i]]-s[li[i]-1]);
//求在W下的Y
return res;
}
int main(void)
{
cin>>n>>m>>S;
for(int i=1;i<=n;i++) cin>>wi[i]>>vi[i];
for(int i=1;i<=m;i++) cin>>li[i]>>Ri[i];
int l=0,r=1e6+10;
while(l<r)
{
int mid=l+r>>1;
if(check(mid)<=S) r=mid;
else l=mid+1;
}
cout<<min(abs(check(r)-S),abs(S-check(r-1)));
}