bzoj4868: [Shoi2017]期末考试(三分法)
4868: [Shoi2017]期末考试
题目:传送门
题解:
Get到一个新姿势...三分法
一开始百度百科的时候下了一跳...中国...的根???
学懂了之后其实运用起来就根二分差不多啊,不过证明...不是很懂%大佬
先喷一波自己:没看到最小值...一直维护的是一个上凸包ORZ
然后知道了三分,计算答案的时候就直接用贪心嘛(比较一下那种不愉快度小就尽量用那种,统计一下当前解一共提前了和延后了多少天),不过因为没有操作可以单独推迟,所以少了一种情况。
再打一波脸: 存在几组数据,使得C = 10 ^ 16(大视野写的真大)有这句话,longlong都爆了啊...加特判ORZ
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 typedef long long LL; 8 LL A,B,C; 9 LL n,m; 10 LL a[1100000],b[1100000]; 11 LL sol(LL x) 12 { 13 LL sum=0; 14 if(A<B) 15 { 16 LL s1=0,s2=0;//表示需要推迟的总天数 和 提前的总天数 17 for(int i=1;i<=m;i++)if(b[i]<x)s1+=(x-b[i]); 18 for(int i=1;i<=m;i++)if(b[i]>x)s2+=(b[i]-x); 19 if(s1>=s2)sum+=(s2*A);//用操作1直接解决 20 else sum+=(s1*A+(s2-s1)*B);//操作1+操作2 21 } 22 else for(int i=1;i<=m;i++)if(b[i]>x)sum+=(b[i]-x)*B;//因为没有操作是单独推迟的,所以少了一种情况 23 for(int i=1;i<=n;i++)if(a[i]<x)sum+=(x-a[i])*C; 24 return sum; 25 } 26 int main() 27 { 28 scanf("%lld%lld%lld",&A,&B,&C); 29 scanf("%lld%lld",&n,&m); 30 for(int i=1;i<=n;i++)scanf("%lld",&a[i]); 31 for(int i=1;i<=m;i++)scanf("%lld",&b[i]); 32 LL l=1,r=1e5,mid,mmid; 33 LL ans1,ans2,ans3,ans4; 34 ans1=ans2=ans2=ans4=0; 35 if(C==1e16) 36 { 37 LL mmin=1e18; 38 for(int i=1;i<=n;i++)mmin=min(mmin,a[i]); 39 printf("%lld\n",sol(mmin)); 40 return 0; 41 } 42 while(l+2<r) 43 { 44 mid=(l+r)/2,mmid=(mid+r)/2; 45 ans1=sol(mid),ans2=sol(mmid); 46 if(ans1==ans2)l=mid,r=mmid; 47 else if(ans1<ans2)r=mmid; 48 else l=mid; 49 } 50 mid=(l+r)/2,mmid=(mid+r)/2; 51 ans1=sol(l),ans2=sol(r),ans3=sol(mid),ans4=sol(mmid); 52 printf("%lld\n",min(min(ans1,ans2),min(ans3,ans4))); 53 return 0; 54 }