题解 P1314 【聪明的质监员】
LinkyChristian · · 题解
既然有那么多dalao发了优质的题解,那我就来一发代码吧。
注明 本题解为纯代码,注释不多,主要是提供一段可读性强的代码,配合其他题解食用更佳。
代码1 可读性较强
#include<bits/stdc++.h>
using namespace std;
typedef long long int lld;
lld n,m,s;
lld w[200010],v[200010],l[200010],r[200010];//w,v,l,r就是原题的意思
lld sumv[200010],sumn[200010];//vi的前缀和,个数的前缀和
lld maxx,minn=0x7f7f7f7f7f,out=0x7f7f7f7f7f;//最大重量和最小重量
lld Y(int W) {
lld ans=0;
for(lld i=1; i<=n; i++) {
if(w[i]>=W) {
sumv[i]=sumv[i-1]+v[i];
sumn[i]=sumn[i-1]+1;
}
else {
sumv[i]=sumv[i-1];
sumn[i]=sumn[i-1];
}
}//前缀和
//公式求解每个区间的Y值之和
for(int i=1; i<=m; i++)
ans+=(sumn[r[i]]-sumn[l[i]-1])*(sumv[r[i]]-sumv[l[i]-1]);
return ans;
}
int main()
{
cin>>n>>m>>s;
for(lld i=1; i<=n; i++) {
cin>>w[i]>>v[i];
if(w[i]>maxx) maxx=w[i];
if(w[i]<minn) minn=w[i];
}
for(lld i=1; i<=m; i++) cin>>l[i]>>r[i];
lld left=minn-1,right=maxx+2,mid,op,low;//确定边界
while(left<=right) {//二分
mid=(left+right)/2,op=Y(mid),low=fabs(s-op);
if(op>s) left=mid+1;
else right=mid-1;
if(low<out) out=low;
}
cout<<out;
return 0;
}
代码2 较为精简(无注释)其实就是压行了一下
#include<bits/stdc++.h>
using namespace std;
typedef long long int lld;
lld n,m,s;
lld w[200010],v[200010],l[200010],r[200010],sumv[200010],sumn[200010],maxx,minn=0x7f7f7f7f7f,out=0x7f7f7f7f7f;
lld Y(int W) {
lld ans=0;
for(lld i=1; i<=n; i++) {
if(w[i]>=W) {sumv[i]=sumv[i-1]+v[i],sumn[i]=sumn[i-1]+1;}
else {sumv[i]=sumv[i-1],sumn[i]=sumn[i-1];}
}
for(int i=1; i<=m; i++) ans+=(sumn[r[i]]-sumn[l[i]-1])*(sumv[r[i]]-sumv[l[i]-1]);
return ans;
}
int main()
{
cin>>n>>m>>s;
for(lld i=1; i<=n; i++) {cin>>w[i]>>v[i];if(w[i]>maxx) maxx=w[i];if(w[i]<minn) minn=w[i];}
for(lld i=1; i<=m; i++) cin>>l[i]>>r[i];
lld left=minn-1,right=maxx+2,mid,op,low;
while(left<=right) {
mid=(left+right)/2,op=Y(mid),low=fabs(s-op);
if(op>s) left=mid+1;else right=mid-1;
if(low<out) out=low;
}
cout<<out;
return 0;
}
A了这道题,祝你们成功(手动滑稽)(玩梗)