【Luogu】P3745期末考试(三分)
题目链接
我是怎么把“期末考试”在本地写成“假期计划”的
qwq????
本题把学生和卷子都排个序,按出成绩最晚时间三分。
三分之后可以O(n)的时间统计答案,因为修改卷子出成绩的时间可以贪心计划。
这里着重了解一下为什么可以三分。
我们可以发现随着出成绩的时间推迟,学生的不偷税愉悦度肯定是越来越大的,换句话说这玩意单调递增。
然而老师的不偷税度一定是越来越小的,换句话说这玩意单调递减。
所以说这俩玩意加起来肯定跟二次函数长得特像。
就可以三分啦。
然而三分是用于实数定义域内的,我们这是整数怎么办?
所以说我们可以三分取得一个较小的区间(我这里定的区间大小=8)
然后对这个区间每一个值都求一遍求解就好啦
#include<cstdio> #include<cstdlib> #include<cctype> #include<cstring> #include<algorithm> #define maxn 200020 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } long long a,b,c; long long n,m; long long q[maxn]; long long d[maxn]; double calc(long long x){ long long rest=0,need=0; for(long long i=1;i<=m;++i) if(q[i]<=x) rest+=x-q[i]; else need+=q[i]-x; double ans=0; if(a<b){ if(need<=rest) ans=a*need; else ans=a*rest+b*(need-rest); } else ans=b*need; for(long long i=1;i<=n;++i) if(d[i]<x){ //if(c==1e16) return 1e18; ans+=(double)(x-d[i])*c; } return ans; } int main(){ a=read(),b=read(),c=read(); n=read(),m=read(); for(long long i=1;i<=n;++i) d[i]=read(); for(long long i=1;i<=m;++i) q[i]=read(); sort(d+1,d+n+1); sort(q+1,q+m+1); long long l=d[1],r=d[n]; while(r-l>8){ long long mid=l+(r-l)/3; long long mmid=l+(r-l)*2/3; if(calc(mid)<=calc(mmid)) r=mmid; else l=mid; } long long ret=l; for(long long i=l;i<=r;++i) if(calc(i)<calc(ret)) ret=i; printf("%.0lf",calc(ret)); return 0; }