二分+模拟,CF1461D - Divide and Summarize

水军大提督  金牌会员 | 2024-6-13 15:33:48 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 663|帖子 663|积分 1989

一、题目

1、题目形貌

   

  2、输入输出

2.1输入

   

  2.2输出

   

  3、原题链接

Problem - 1461D - Codeforces


二、解题报告

1、思绪分析

我们发现每次分裂操作效果都是固定的
我们从初始序列分裂出两个确定的子序列,两个确定的子序列又分裂出4个确定的子序列
那么也就是说我们最终能够分裂出的子序列的数量是O(n)的
我们预处理出所有的子序列就预处理出了所有可以得到的和(当然这个和要在分裂的过程中维护)
而分裂要求我们得到小于即是mid的部门和大于的部门
以是我们须要对原序列进行排序,模拟的过程通过二分来找到分裂的位置
同时预处理前缀和以便每次分裂前都记录一下当前得到的值
值得注意的是nums[l] = nums[r]的时候阐明当前子序列是雷同的,我们无法继承向下分裂
2、复杂度

   时间复杂度: O(NlogN)空间复杂度:O(N)
  
3、代码详解

复制代码
  1. #include <bits/stdc++.h>
  2. using PII = std::pair<int, int>;
  3. using i64 = long long;
  4. std::mt19937 rnd(std::chrono::steady_clock::now().time_since_epoch().count());
  5. const int P = [](int x) {
  6.     auto isprime = [](int x) {
  7.         if (x <= 1) return false;
  8.         for (int i = 2; i <= x / i; i ++ )
  9.             if (x % i == 0) return false;
  10.         return true;
  11.     };
  12.     while (!isprime(x)) x ++;
  13.     return x;
  14. }(rnd() % 900000000 + 100000000);
  15. void solve() {
  16.     /*  直接模拟    */
  17.     int N, Q, s;
  18.     std::cin >> N >> Q;
  19.     std::vector<int> nums(N);
  20.     std::vector<i64> pre(N + 1);
  21.     for (int i = 0; i < N; i ++ )
  22.         std::cin >> nums[i];
  23.     std::sort(nums.begin(), nums.end());
  24.     for (int i = 0; i < N; i ++ )
  25.         pre[i + 1] += nums[i] + pre[i];
  26.    
  27.     std::vector<std::array<int, 2>> segs { { 0, N - 1 } };  segs.reserve(N);
  28.     std::unordered_set<i64> st;
  29.     while (segs.size()) {
  30.         std::vector<std::array<int, 2>> nxt;
  31.         for (auto& [l, r] : segs) {
  32.             st.insert(pre[r + 1] - pre[l] + P);
  33.             if (nums[l] != nums[r]) {
  34.                 int mid = std::upper_bound(nums.begin(), nums.end(), (nums[l] + nums[r]) >> 1) - nums.begin();
  35.                 nxt.insert(nxt.end(), { { l, mid - 1 }, { mid, r } });
  36.             }
  37.         }
  38.         segs = std::move(nxt);
  39.     }
  40.     for (int i = 0, s; i < Q; i ++) {
  41.         std::cin >> s;
  42.         if (st.count(1LL * s + P))
  43.             std::cout << "YES\n";
  44.         else
  45.             std::cout << "NO\n";
  46.     }
  47. }
  48. int main () {
  49.     std::ios::sync_with_stdio(false);   std::cin.tie(0);  std::cout.tie(0);
  50.     int _ = 1;
  51.     std::cin >> _;
  52.     while (_ --)
  53.         solve();
  54.     return 0;
  55. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

水军大提督

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表