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 }

 

posted @ 2018-03-22 19:30  CHerish_OI  阅读(383)  评论(0编辑  收藏  举报