二分答案的大水题。二分一下W,然后记录一下前缀满足wi≤W的个数,前缀满足这个条件的vi的和,check的时候直接O(n+m)的check就行了。
记得开long long
#include <iostream> #include <cmath> #include <cstdio> #include <cstring> using namespace std; typedef long long ll; const int N=200005; int n,m,sum1[N],w[N],v[N],l[N],r[N]; ll S,sumv[N]; ll ck(int mid) { for(int i=1;i<=n;i++) { sum1[i]=sum1[i-1]+(w[i]>=mid); sumv[i]=sumv[i-1]+(v[i]*(w[i]>=mid)); } ll sum=0; for(int i=1;i<=m;i++) { sum=(sum+(sum1[r[i]]-sum1[l[i]-1])*(sumv[r[i]]-sumv[l[i]-1])); } return sum; } int main() { scanf("%d%d%lld",&n,&m,&S); for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&v[i]); for(int i=1;i<=m;i++) scanf("%d%d",&l[i],&r[i]); int L=0,R=1e6; while(L<=R) { int mid=L+R>>1; ll tp=ck(mid); if(tp>S) L=mid+1; else if(tp==S) { printf("%d",0); return 0; } else R=mid-1; } printf("%d ",(int)min(abs(ck(R)-S),abs(S-ck(L)))); return 0; }