2018acm区域赛青岛

C,zoj4062

最小值最大化,典型的二分答案

关键是judge函数怎么写

除此之外,写出judge也很难ac,此题尽是坑点,写的我一把辛酸泪啊QAQ~~

什么最后一个要特判,不加次数。。

什么很容易超ll。。

什么负数。。

什么超时。。

都要及时跳出才行

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=1e5+10;
 7 
 8 int n;
 9 ll m;
10 ll a[maxn],d[maxn];
11 
12 ll judge(ll k)
13 {
14     //memset(d,0,(n+1)*sizeof(ll));
15     //memset(d,0,sizeof(d));//1520ms
16     for(int i=0;i<=n+1;i++) d[i]=0;//630ms
17     
18     ll cnt=0;
19     for(int i=1;i<=n;i++)
20     {
21         if(i==n && d[i]>=k) break;//坑点1,最后一个特判
22         
23         cnt++; d[i]+=a[i];//注意这个细节,d[i]+=a[i]要放到continue前面,后面必错!(先把每一步必须的一步加上,不要和后面的放在一起算,不容易错)
24         if(d[i]>=k) continue;//坑点2,不要一直加,会超ll,同时关键防止了下面负数情况!!
25         //d[i]+=a[i];//之前以为放这一直错QAQ
26         
27         ll c=(k-d[i])/a[i];//坑点3,这里(通过上面continue)要防止了过大变负数
28         if((k-d[i])%a[i]) c++;
29         cnt+=2*c;
30         d[i]+=c*a[i];
31         d[i+1]+=c*a[i+1];
32         
33         if(cnt>m) break;
34     }
35     return cnt;
36 }
37 
38 int main()
39 {
40     ios::sync_with_stdio(0);
41     cin.tie(0);
42 
43     int T;
44     cin>>T;
45     while(T--)
46     {
47         cin>>n>>m;
48         ll mn=1e5+10;
49         for(int i=1;i<=n;i++) cin>>a[i], mn=min(mn,a[i]);
50 
51         ll l=0, r=mn*m,ans=0;
52         while(l<=r)
53         {
54             ll mid=(l+r)>>1;
55             if(judge(mid)<=m) 
56             {
57                 ans=mid;
58                 l=mid+1;
59             }
60             else r=mid-1;
61         }
62         cout<<ans<<endl;
63     }
64 }

完。

猜你喜欢

转载自www.cnblogs.com/redblackk/p/9999184.html