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/

  • 相关阅读:
    mysq 日期相减
    说说时间观与时间管理——北漂18年(71)
    ionic之切换开关
    ionic之单选框
    SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE locks在RR模式下可以看到最新的记录
    14.5.2.3 Consistent Nonlocking Reads 一致性非锁定读
    14.5.2.2 autocommit, Commit, and Rollback
    14.5.2 事务隔离级别
    对于唯一索引使用唯一条件搜索, InnoDB 只锁定找到的index record,不是它之前的区间
    mysql explain 解释
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/6841517.html
Copyright © 2011-2022 走看看