• Codeforces Round #799 (Div. 4)


    前面的题感觉没啥好写的,咕咕咕

    H. Gambling

    题意

    给定一个长度为\(n\)的数组\(x\),问使得最终钱数最大的\(a, l, r\)

    收益的计算方式为,初始有\(1\)的钱,从\(x_l\)\(x_r\),遇到一个\(x_i = a\)钱就乘二,反之除2。这里的除法不取整,就是说会搞出\(\frac{1}{2}\)这种数字。

    其中\(1 \le n \le 2 \times {10}^5, 1 \le x_i \le {10}^9\)

    思路

    转化一下就是最终的钱等于\(2^{\sum_{i = l}^{r} [x_i = a] - \sum_{i = l}^{r} [x_i \ne a]}\)。然后为了方便计算比较指数的大小就可以了。

    这个问题可以转化成最大子区间和的问题,然后就是DP了。

    具体的转化为:对于某个值\(a\),构造一个权值数组\(w\),如果\(x_i = a\)就令\(w_i = 1\),反之令\(w_i = -1\),那么\(w\)的最大子区间和就是答案。

    不加任何优化需要\(O(n^2)\)次转移必TLE,需要加点优化。

    观察可得最终答案区间的两端的值一定等于\(a\),因为把两端不等于\(a\)的值去掉收益为正。由此第\(i\)个位置只需要考虑\(a = x_i\)的情况。

    现在就只需要\(O(n)\)次转移了。

    AC代码
    // Problem: H. Gambling
    // Contest: Codeforces - Codeforces Round #799 (Div. 4)
    // URL: https://codeforces.com/contest/1692/problem/H
    // Memory Limit: 256 MB
    // Time Limit: 2000 ms
    //
    // Powered by CP Editor (https://cpeditor.org)
    
    #include <bits/stdc++.h>
    
    #define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    #define freep(p) p ? delete p, p = nullptr, void(1) : void(0)
    
    #ifdef BACKLIGHT
    #include "debug.h"
    #else
    #define logd(...) ;
    #endif
    
    using i64 = int64_t;
    using u64 = uint64_t;
    
    void solve_case(int Case);
    
    int main(int argc, char* argv[]) {
      CPPIO;
      int T = 1;
      std::cin >> T;
      for (int t = 1; t <= T; ++t) {
        solve_case(t);
      }
      return 0;
    }
    
    void solve_case(int Case) {
      int n;
      std::cin >> n;
    
      std::vector<int> x(n);
      for (int i = 0; i < n; ++i)
        std::cin >> x[i];
    
      std::map<int, std::array<int, 3>> dp;
      int max_gain = 0, a, l, r;
      for (int i = 0; i < n; ++i) {
        int v = x[i];
        if (!dp.count(v)) {
          dp[v] = {1, i, i};
        } else {
          auto [gain, l, r] = dp[v];
          int cost = i - r - 1;
          if (gain >= cost) {
            dp[v] = {gain - cost + 1, l, i};
          } else {
            dp[v] = {1, i, i};
          }
        }
    
        if (dp[v][0] > max_gain) {
          max_gain = dp[v][0];
          a = v;
          l = dp[v][1];
          r = dp[v][2];
        }
      }
    
      std::cout << a << " " << l + 1 << " " << r + 1 << "\n";
    }
    
    
  • 相关阅读:
    rocketMQ
    RocketMQ 事务消息
    Serial,Parallel,CMS,G1四大GC收集器特点小结
    CMS垃圾收集器与G1收集器
    CMS垃圾回收过程
    MySQL中EXPLAIN解释命令 查看索引是否生效
    redis持久化的几种方式
    深入浅出数据库索引原理
    Java中堆内存和栈内存详解
    jvm垃圾回收机制
  • 原文地址:https://www.cnblogs.com/zengzk/p/16376984.html
Copyright © 2020-2023  润新知