以P1314 聪明的质监员为例
第一种写法:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long LL; const int N=200000+10; int v[N],w[N],n,m; int l[N],r[N]; int sum[N],cnt[N]; LL f(int W) { memset(sum,0,sizeof(sum)); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++) { if(w[i]>=W) { cnt[i]=cnt[i-1]+1; sum[i]=sum[i-1]+v[i]; } else { cnt[i]=cnt[i-1]; sum[i]=sum[i-1]; } } LL res=0; for(int i=1;i<=m;i++) { res=res+(sum[r[i]]-sum[l[i]-1])*(cnt[r[i]]-cnt[l[i]-1]); } return res; } int main() { LL S; cin>>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=1000000+1,mid; while(L<R) //这里求的是 递减函数的 函数值严格小于S的 点的横坐标 的最小值 { mid=(L+R)/2; //下取整的板子 if(f(mid)<S) R=mid; //mid处函数值小于S,不能保证mid-1处函数值小于S,只能将R缩小至mid else L=mid+1; //mid处函数值大于等于S,可直接令L缩至mid+1 最终L和R必相等,不会死循环 } cout<<min(S-f(L),f(L-1)-S)<<endl; return 0; }
第二种写法:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long LL; const int N=200000+10; int v[N],w[N],n,m; int l[N],r[N]; int sum[N],cnt[N]; LL f(int W) { memset(sum,0,sizeof(sum)); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++) { if(w[i]>=W) { cnt[i]=cnt[i-1]+1; sum[i]=sum[i-1]+v[i]; } else { cnt[i]=cnt[i-1]; sum[i]=sum[i-1]; } } LL res=0; for(int i=1;i<=m;i++) { res=res+(sum[r[i]]-sum[l[i]-1])*(cnt[r[i]]-cnt[l[i]-1]); } return res; } int main() { LL S; cin>>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=1000000+1,mid; while(L<R) //这里求的是 递减函数的 函数值大于等于S的 点的横坐标 的最大值 { mid=(L+R+1)/2; //上取整的板子 if(f(mid)>=S) L=mid; //mid处函数值大于等于S,不能保证mid+1处函数值大于等于S,只能将L缩小至mid else R=mid-1; //mid处函数值小于S,可直接令R缩至mid-1 最终L和R必相等,不会死循环 } cout<<min(f(L)-S,S-f(L+1))<<endl; return 0; }