zoukankan      html  css  js  c++  java
  • UVAlive7501 Business Cycle 2015ECfinal B(二分模板)

    题意:给你一个环,环有n个点,编号0~n-1,每个点有一定的权值,从点0出发沿编号走,到达某一个节点则把目前总权值加上这个节点的权值,如果结果小于0则变成0。现在给你最多可以走的步数P和最大需要到达的权值大小G,问你需要的最小的初始权值为多少,能在P步内能够产生的最大权值大于等于G


    题解:很容易想到初始权值越大,经过同样步数能够得到的权值就越大,当然是非严格递增的。那么直接想办法二分寻找初始权值就可以。但是如果步数太大了就没法模拟了,所以要消除步数的影响。步数的影响主要来源于在走环的过程中可能由负数变为0,不然直接预处理就可以了。所以先找出走环过程能够始终不小于0所需要的最小权值sum,当初始权值小于sum时会在过程中变为0,那么用这个初始权值走一圈以上就等效于用0走一圈以上,当然走一圈以内是不能等效的,一圈以内所能得到的最大权值可能大于初始为0开始走。当初始权值大于等于sum时走一圈如果总权值减小那么可以到达的最大权值必定在一圈以内,如果增大则需要分情况讨论了,具体见代码,比较坑就是比较是否是否能到达所需要的G时可能爆long long ,,,,

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <cstdio>
      4 #include <cmath>
      5 using namespace std;
      6 typedef long long ll;
      7 const ll maxn = 1e5 + 10;
      8 ll a[maxn];
      9 ll n,g,p;
     10 ll getm(ll u,ll num) { //初始为u走num步过程中可得的最大值
     11     ll max1 = u;
     12     for(ll i = 0; i < num; i++) {
     13         u += a[i];
     14         if(u < 0) u = 0;
     15         max1 = max(max1,u);
     16     }
     17     return max1;
     18 }
     19 int main() {
     20    // freopen("in.txt","r",stdin);
     21     //freopen("out.txt","w",stdout);
     22     ll T;
     23     cin>>T;
     24     ll cas = 0;
     25     //ll l = (ll)3e18+7;
     26     //cout<<l<<endl;
     27     while(T--) {
     28         cas++;
     29         scanf("%lld%lld%lld",&n,&g,&p);
     30         for(ll i = 0; i < n; i++) scanf("%lld",&a[i]);
     31         ll sum = 0,sum0 = 0;//sum 为始终不小于0的界限,sum0初始为走一圈所得的值
     32         for(ll i = 0; i < n; i++) {
     33             sum0 += a[i];
     34             if(sum0 < 0) {
     35                 sum -= sum0;
     36                 sum0 = 0;
     37             }
     38         }
     39         //cout<<sum<<" "<<sum0<<endl;
     40         ll sums = sum;//sums为sum走一圈所得的值
     41         for(ll i = 0; i < n; i++) sums += a[i];
     42         sums -= sum;
     43         ll max0;//max0为0走一圈以上所得的最大值
     44         if(p > n) {
     45             if(sum0 < sum) {
     46                 if(p < 2*n)
     47                     max0 = getm(sum0,p - n);
     48                 else
     49                     max0 = getm(sum0 , n);
     50             }
     51             else {
     52                 if(p < 2 * n) max0 = getm(sum0,p - n);
     53                 else {
     54                     if(sums > 0) {
     55                        if((g-sum0)/sums < p/n-1)//每一圈都能增大sums,当走最多圈是否能到达所需要的值
     56                         max0 = g+1;
     57                       else{
     58                         max0 = sum0 + sums*(p/n-1);
     59                         max0 = getm(max0,p % n);
     60                         if(p/n > 1) {//当少走一圈时是否可以到达更大的值
     61                             ll max1 = (p/n - 2)*sums + sum0;
     62                             max1 = getm(max1,n);
     63                             max0 = max(max0,max1);
     64                         }
     65                     }
     66                     }
     67                     else {
     68                         max0 = getm(sum0,n);
     69                     }
     70                 }
     71             }
     72         }
     73 
     74         ll l = 0,r = g;
     75         ll xans = -1;
     76         while(l <= r) {
     77             ll mid = l + (r - l) / 2;
     78             ll ans = mid;
     79             if(p <= n){
     80                 ans = getm(mid,p);
     81             }
     82             else {
     83                 //cout<<ans<<endl;
     84                 if(mid < sum) {
     85                     ans = getm(mid,n);
     86                     ans = max(ans,max0);
     87              //   cout<<ans<<endl;
     88                 }
     89                 else {
     90                     if(sums > 0) {
     91                         //cout<<sums*(p/n)<<endl;
     92                         if((g-mid)/sums < p/n-1) ans = g+1;//同上
     93                         else{
     94                         ans += sums*(p/n);
     95                         ans = getm(ans,p % n);
     96                       // cout<<ans<<endl;
     97                         if(p/n >= 1) {
     98                             ll ans1 = 0;
     99                             ans1 = sums*(p/n-1) + mid;
    100                             ans1 = getm(ans1,n);
    101                             ans = max(ans,ans1);
    102                         }
    103                         }
    104                     }
    105                     else ans = getm(mid,n);
    106                    // cout<<ans<<endl;
    107                 }
    108             }
    109           //  cout<<l<<" "<<r<<" "<<mid<<" "<<ans<<endl;
    110             if(ans >= g) r = mid - 1, xans = mid;
    111             else l = mid + 1;
    112         }
    113         printf("Case #%lld: %lld
    ",cas,xans);
    114     }
    115 
    116     return 0;
    117 }
  • 相关阅读:
    菜鸟笔记 -- Chapter 6.2.6 内部类
    菜鸟笔记 -- Chapter 6 面向对象
    菜鸟笔记 -- Chapter 6.1 面向对象概述
    菜鸟笔记 -- Chapter 4.7 代码注释与编码规范
    菜鸟笔记 -- Chapter 4 Java语言基础
    小白袍 -- Chapter 1.4.1.1 URL编码的理论解读
    小白袍 -- Chapter 1.1 避不开的编解码
    小白袍 -- Chapter 1 Java中的Encode与Decode
    菜鸟崛起 Ajax
    软件测试
  • 原文地址:https://www.cnblogs.com/shimu/p/5948176.html
Copyright © 2011-2022 走看看