topcoder srm 714 div1
problem1 link
倒著想。每次添加一個右括號再添加一個左括號,直到還原。那么每次的右括號的選擇范圍為當前左括號后面的右括號減去后面已經使用的右括號。
problem2 link
令$h(x)=\sum_{i=1}^{x}g(i)$,那么答案為$h(R)-h(L-1)$。對于$h(x)$:
(1)如果$x\leq 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// backlength += 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/
轉載于:https://www.cnblogs.com/jianglangcaijin/p/6841517.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的topcoder srm 714 div1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中的数据类型,存储,实现
- 下一篇: CentOS 6 nginx(Tengi