zoukankan      html  css  js  c++  java
  • topcoder srm 714 div1

    problem1 link

    倒着想。每次添加一个右括号再添加一个左括号,直到还原。那么每次的右括号的选择范围为当前左括号后面的右括号减去后面已经使用的右括号。

    problem2 link

    令$h(x)=sum_{i=1}^{x}g(i)$,那么答案为$h(R)-h(L-1)$。对于$h(x)$:

    (1)如果$xleq K$,那么$h(x)=0$

    (2)否则对于$[K+1,x]$之间的所有偶数来说,对答案的贡献为$even+h(frac{x}{2})-h(frac{K}{2})$,其中$even=frac{x}{2}-frac{K}{2}$,$h(frac{K}{2})=0$。奇数对答案的贡献为$odd*2+h(frac{x+K}{2})$,$odd=x-K-even$。其中$[frac{x}{2}+1,frac{x+K}{2}]$之间的数字并不多,可以暴力。

    problem3 link

    下面第二个链接有关于714-div2-hard的题目的线形解法。它的思路记录过往的supply剩余总和以及demand的总和(如果supply大于 demand就抵消)。同时如果demand大于0还要记录最早的demand需要的位置。这样当出现新的supply并且足够抵消过去的demand时就回退回去满足demand然后返回。直到最后。

    这道题与上面的区别是坐标会有负数并且可以在任意地方停止。所以可以假设先到达最左侧的某个地方,然后就跟上面类似了。对于在任何地方停止,可以贪心地计算。具体实现细节看代码以及注释。

    code for problem1

    #include <string>
    
    class ParenthesisRemoval {
     public:
      int countWays(const std::string &s) {
        constexpr int kMod = 1000000007;
        int n = static_cast<int>(s.size());
        long long ans = 1;
        for (int i = n - 1, t = 0; i >= 0; --i) {
          if (s[i] == ')') {
            ++t;
          } else {
            ans = ans * t % kMod;
            --t;
          }
        }
        return ans;
      }
    };

    code for problem2

    class NAddOdd {
     public:
      long long solve(long long L, long long R, int K) {
        return Dfs(R, K) - Dfs(L - 1, K);
      }
    
     private:
      long long g(long long x, int K) {
        long long ans = 0;
        while (x > K) {
          ++ans;
          if (x % 2 == 1) {
            x += K;
          } else {
            x >>= 1;
          }
        }
        return ans;
      }
      long long Dfs(long long x, int k) {
        if (x <= k) {
          return 0;
        }
    
        long long even = (x >> 1) - (k >> 1);
        long long odd = x - k - even;
        long long ans = even + (odd << 1) + (Dfs(x >> 1, k) << 1);
        for (long long i = (x >> 1) + 1; i <= ((x + k) >> 1); ++i) {
          ans += g(i, k);
        }
        return ans;
      }
    };

    code for problem3

    #include <algorithm>
    #include <vector>
    
    class Salesman {
     public:
      int minMoves(std::vector<int> pos, std::vector<int> delta) {
        int result = Compute(pos, delta);
        std::reverse(pos.begin(), pos.end());
        std::reverse(delta.begin(), delta.end());
        for (auto &x : pos) {
          x *= -1;
        }
        result = std::min(result, Compute(pos, delta));
        return result;
      }
    
     private:
      int Compute(const std::vector<int> &pos, const std::vector<int> &delta) {
        int n = static_cast<int>(pos.size());
        int last_need = n - 1;
        while (last_need >= 0 && delta[last_need] >= 0) {
          --last_need;
        }
        if (last_need < 0) {
          return 0;
        }
        std::vector<int> next_need(n + 1, n);
        for (int i = n - 1; i >= 0; --i) {
          if (delta[i] < 0) {
            next_need[i] = i;
          } else {
            next_need[i] = next_need[i + 1];
          }
        }
        int result = std::numeric_limits<int>::max();
        for (int left = 0; left < n; ++left) {
          int right = last_need;
          int sum = 0;
          for (int i = left; i <= right; ++i) {
            sum += delta[i];
          }
          while (sum < 0 && right + 1 < n) {
            sum += delta[++right];
          }
          if (sum < 0) {
            break;
          }
          // The left is start and must visit right to get all supplys.
          int length = std::abs(pos[left]) + pos[right] - pos[left];
          int supply = 0;
          int demand = 0;
          int go_back_pos = 0;
          for (int i = left; i <= right; ++i) {
            if (delta[i] < 0) {
              int curr_demand = -delta[i];
              if (demand == 0 && supply >= curr_demand) {
                supply -= curr_demand;
              } else {
                if (demand == 0) {
                  // If the pos[i] is negative, then just keep go_back_pos as
                  // origin and need goto right and back to pos[i]
                  go_back_pos = std::max(go_back_pos, pos[i]);
                }
                demand += curr_demand;
              }
            } else {
              supply += delta[i];
              if (demand > 0 && supply >= demand) {
                supply -= demand;
                demand = 0;
                // Here you have a choose that return to previous demand pos
                // immediately and back and in future you will no need to return
                // back
                length += 2 * std::max(0, pos[i] - go_back_pos);
              }
            }
            int final_stop_pos =
                demand > 0 ? go_back_pos : pos[std::min(right, next_need[i + 1])];
            result =
                std::min(result, length + std::max(0, pos[right] - final_stop_pos));
          }
          if (delta[left] < 0) {
            break;
          }
        }
        return result;
      }
    };
    

      

    参考:

    https://codeforces.com/blog/entry/50602

    https://www.topcoder.com/blog/single-round-match-714-editorials/

  • 相关阅读:
    所有的工作目录 都要svn_开头,并且要进行svn同步,你能保证你不删除,你保证不了非你!
    火狐删除配置文件 会删除目录下所有文件 切记不要把配置文件建立在桌面 恢复软件:易我数据恢复向导 9.0 DiskGenius500
    谷歌全屏脚本 start chrome.exe --kiosk http://www.baidu.com
    bat2exe 就是这么简单 白研究半天VC++了
    火狐加载用户配置文件 "C:XXXMozilla Firefoxfirefox.exe" http://192.168.1.1:8080 -profile ../kkk
    https://quotefancy.com/ 经典句子(英语) 真是特别好~
    (function(){})() 立即执行函数
    jekyll 将纯文本转化为静态网站和博客 静态网站生成器
    vue 发布build 本地设置 相对路径 两个地方 一个根目录用./ css文件里面用../../ 【也不好用,还是得手改】
    iview构建 初始化的时候不要装ESlint 太烦人了
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/6841517.html
Copyright © 2011-2022 走看看