洛谷1314 聪明的质监员
洛谷1314 聪明的质监员
原题链接
交题记录
23:28 AC
题还算水。
题解
10分算法
写挂的吧。。。
30分算法
暴力枚举统计答案???
50分算法
二分+暴力check。
AC算法
Y随W增加而减小,可以二分一个W。
\(W\in[0,10^6+1]\)
然后如何check
可以用到前缀和优化。
可以发现每一次check的前缀和是不同的,所以check一次就求一次前缀和。。。
怎么求?s表示\(>=w\)的数的和的前缀和,tot表示\(>=w\)的数个数的前缀和。
s即对应\(\sum_{j}v_j\),tot对应\(\sum_{j}1\).
每次\(O(n)\)求出s,tot后每个区间就可\(O(1)\)算了。
\(O(n+m)\)的check。
加上二分总复杂度\(O(log_210^6*(n+m))\)
注意:二分最后l==r-2,这样不会漏计答案(可能是我傻了)
Code
// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
#define rep(a,b,c) for(rg ll a=b;a<=c;a++)
#define drep(a,b,c) for(rg ll a=b;a>=c;a--)
#define erep(a,b) for(rg ll a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il ll gi(){
rg ll x=0,f=1;rg char ch=getchar();
while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxn=200010;
ll n,m,S,w[maxn],v[maxn],L[maxn],R[maxn];
ll s[maxn],tot[maxn];
il ll check(int W){
rep(i,1,n){
s[i]=s[i-1],tot[i]=tot[i-1];
if(w[i]>=W)s[i]+=v[i],++tot[i];
}
ll ret=-S;
rep(i,1,m)ret+=(s[R[i]]-s[L[i]-1])*(tot[R[i]]-tot[L[i]-1]);
return ret;
}
int main(){
n=gi(),m=gi(),S=gi();
rep(i,1,n)w[i]=gi(),v[i]=gi();
rep(i,1,m)L[i]=gi(),R[i]=gi();
ll l=0,r=1000001,mid,ck;
while(l<r-2){
mid=l+r>>1;
ck=check(mid+1);
if(!ck){puts("0");return 0;}
if(check(mid+1)<0)r=mid+1;
else l=mid;
}
printf("%lld\n",min(abs(check(l+1)),min(abs(check(l)),abs(check(r)))));
return 0;
}
博主是蒟蒻,有问题请指出,谢谢!
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。