洛谷 1314 聪明的质监员——二分答案
题目:https://www.luogu.org/problemnew/show/P1314
二分答案。把询问挂在右边界上,就能用前缀查询了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=2e5+5; int n,m,w[N],v[N],hd[N],xnt,to[N],nxt[N],l,r,mid,ct[N]; ll S,ans=1e13,sm[N],sum; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return fx?ret:-ret; } void add(int x,int y) { to[++xnt]=y; nxt[xnt]=hd[x]; hd[x]=xnt; } int main() { n=rdn(); m=rdn(); scanf("%lld",&S); for(int i=1;i<=n;i++) { w[i]=rdn();v[i]=rdn(); r=max(r,w[i]); } r++; for(int i=1,x,y;i<=m;i++) { x=rdn(); y=rdn(); add(y,x-1); } while(l<=r) { mid=l+r>>1; sum=0; for(int i=1;i<=n;i++) { sm[i]=sm[i-1]+(w[i]>=mid?v[i]:0); ct[i]=ct[i-1]+(w[i]>=mid?1:0); for(int j=hd[i];j;j=nxt[j]) sum+=(sm[i]-sm[to[j]])*(ct[i]-ct[to[j]]); } if(sum>=S) ans=min(ans,sum-S),l=mid+1; else ans=min(ans,S-sum),r=mid-1; } printf("%lld\n",ans); return 0; }