首页 > 其他分享 >CF1239E Turtle 题解

CF1239E Turtle 题解

时间:2024-09-22 21:49:42浏览次数:11  
标签:Turtle std pre suf int 题解 sum CF1239E 权值

Description

一只乌龟从 \(2 \times n\) 的棋盘的左上角走到右下角,只能往下或往右,需要给出一种方案来分配 \(2n\) 个数字使得乌龟走过的路径上的数之和的最大值最小。

\(2\leq n\leq 25,0\leq a_{1,i},a_{2,i}\leq 5\times 10^4\)。

Solution

设 \(pre_{i}=\sum_{j=1}^{i}{a_{1,i}},suf_i=\sum_{j=i}^{n}{a_{2,i}}\)。一组方案的权值即为 \(\max\left\{pre_i+suf_i\right\}\)。

先考虑固定两行数分别选的数后每行最终是怎么排的。

容易发现对于第一行,如果 \(a_{1,i}>a_{1,i+1}\),将 \(a_{1,i}\) 和 \(a_{1,i+1}\) 交换后,在第 \(i\) 列的权值变小其余不变,所以第一行一定是从小到大排列。第二行同理,为从大到小排列。

同时由于 \((pre_{i+1}+suf_{i+1})-(pre_i+suf_i)=a_{1,i+1}-a_{2,i}\) 且 \(a_{1,i}\) 递增,\(a_{2,i}\) 递减。所以对于一组方案,每列的权值构成一个下凸函数,最大权值即为 \(pre_1+suf_1\) 或 \(pre_n+suf_n\)。

于是一组方案的权值为 \(\max\left\{a_{1,1}+\sum{a_{2,i},a_{2,n}+\sum{a_{1,i}}}\right\}=a_{1,1}+a_{2,n}+\max\left\{\sum_{i=2}^{n}{a_{1,i}},\sum_{i=1}^{n-1}{a_{2,i}}\right\}\)。

但是这样仍然做不了,因为 \(a_{1,1}\) 和 \(a_{2,n}\) 的权值不确定。

但是注意到 \(a_{1,1}\) 和 \(a_{2,n}\) 一定存在一个是全局最小值,而另一个经过调整一定可以变成次小值。所以题目转化为了要将剩余的 \(2n-2\) 个数平均分成两组,使得这两组数的和的差的绝对值最小,bitset 优化背包即可。

时间复杂度:\(O\left(\frac{n^2\sum a_{i,j}}{\omega}\right)\)。

Code

#include <bits/stdc++.h>

// #define int int64_t

const int kMaxN = 30, kMaxS = 1.25e6 + 5;

int n;
int a[kMaxN * 2];
std::bitset<kMaxS> f[kMaxN * 2][kMaxN];
std::vector<int> v[2];

void print(int i, int j, int k) {
  if (i == 2) return;
  if (f[i - 1][j][k]) v[0].emplace_back(a[i]), print(i - 1, j, k);
  else v[1].emplace_back(a[i]), print(i - 1, j - 1, k - a[i]);
}

void dickdreamer() {
  std::cin >> n;
  for (int i = 1; i <= 2 * n; ++i) std::cin >> a[i];
  std::sort(a + 1, a + 1 + 2 * n);
  int sum = std::accumulate(a + 3, a + 1 + 2 * n, 0);
  f[2][0][0] = 1;
  for (int i = 3; i <= 2 * n; ++i) {
    for (int j = 0; j <= std::min(i - 3, n - 1); ++j) {
      f[i][j] |= f[i - 1][j];
      f[i][j + 1] |= (f[i - 1][j] << a[i]);
    }
  }
  int ans = 1e9, s = 0;
  for (int i = 0; i <= sum; ++i) {
    if (f[2 * n][n - 1][i] && std::max(i, sum - i) < ans) {
      ans = std::max(i, sum - i);
      s = i;
    }
  }
  v[0] = {a[1]}, v[1] = {a[2]};
  print(2 * n, n - 1, s);
  std::sort(v[0].begin(), v[0].end());
  std::sort(v[1].begin(), v[1].end(), std::greater<>());
  for (auto x : v[0]) std::cout << x << ' ';
  std::cout << '\n';
  for (auto x : v[1]) std::cout << x << ' ';
  std::cout << '\n';
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1;
  // std::cin >> T;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

标签:Turtle,std,pre,suf,int,题解,sum,CF1239E,权值
From: https://www.cnblogs.com/Scarab/p/18425944

相关文章

  • P5975 photo 题解
    Solution先离散化,记\(f(l,r,p)\)为覆盖了\([l,r]\)区间内纵坐标\(\gep\)的点最少矩形个数。则:\[f(l,r,p)=\min(f(l,r,p),f(l,mid,p)+f(mid+1,r,p))\]\[f(l,r,p)=\min(f(l,r,p),f(l,r,res)+1)\]令\(h\)为用面积为\(S\)的矩形去覆盖\([l,r]\)区间的高度,即\(S/(r......
  • P9192 Pareidolia 题解
    Statement给串\(t\),定义\(B(s)\)为\(s\)删一些字符后能出现最多多少个bessie,\(A(t)\)表示对\(t\)的所有子串\(s\)求\(B(s)\)的和,有\(q\)次单点修改,每次改完输出\(B(s)\).Solution动态dp,但是带矩乘\(6^3\)常数,不好.还是考虑分治咋做.现在有区间\([l,mid],......
  • P3703 树点涂色 题解
    Statement树,每个点有一个颜色,初始每个点颜色互不相同到根链涂上新颜色链颜色数\(u\)子树内点\(v\)到根路径的最多颜色数Solution首先,相同颜色的点一定构成一条从下往上的链考虑LCT,维护一个性质:一条实链的点的颜色相同.于是\(u\)到根的颜色数\(=\)\(u\)到根的虚......
  • 最长公共子串 题解
    StatementQ7.1.2.4,时限4s给一个串,定义\(\mathrm{LCS}\)为最长公共子串长度,\(q\)次询问,每次给出\(l,r\),求\[\operatorname{xor}_{i=1}^{r-l+1}\{i+\mathrm{LCS}(S[l,l+i-1],S[l+i-1,r])\}\]\(n\le10^5,q\le30\)Solutiontag:SA,线段树维护分治结构,orzhunction题目就是......
  • BZOJ 2555 = P5212 SubString 题解
    Statement给你一个字符串 \(\text{init}\),要求你支持两个操作:在当前字符串的后面插入一个字符串;询问字符串 \(s\) 在当前字符串中出现了几次?(作为连续子串)你必须在线支持这些操作。Solutionextend中link[cur]=q,相当于link,链加新建copy那里,相当于link,cut,链加询......
  • 2024 秋季模拟赛题解
    2024秋季模拟赛题解CSP-S模拟赛2024.9.8CSP-S模拟赛28T1签到题。对\(b\)分解质因数后便容易求解。T2考虑枚举\(\gcd(S)\)的取值\(x\),则\(\operatorname{lcm}(S)=m-x\)。那么同时变形\(\gcd\)和\(\operatorname{lcm}\)变为\(\gcd(S)=1,\operatorname{lcm}......
  • BZOJ 3277 串 题解
    Statement给 \(n\) 个串,问每个串有多少子串是所有 \(n\) 个串中至少 \(k\) 个串的子串。Solution1%%注意到\(\text{LCP}\)在后缀排序后一定是连续的一段,包含一个串的区间是连续的先预处理出对于所有左端点\(l\),最左的\(r\)满足\([l..r]\)中出现了至少\(k\)个......
  • BZOJ 4310 跳蚤 题解
    Statement把\(S\)分成不超过\(k\)段,使每段的最大子串中的最大串最小。输出这个串。Solution按排名二分这个串,check中从右往左贪心地划分,需要实现\(O(1)\)比较两个子串大小。#include<bits/stdc++.h>usingnamespacestd;#definerep(i,j,k)for(inti=(j);i<......
  • BZOJ 4545 DQS 的 trie 题解
    Statement维护一棵树,边权\(\in\{\texttta,\textttb,\textttc\}\),根为\(1\),定义这棵树的子串为从\(1\)走到所有点构成的字符串的所有后缀,需要支持以下操作:问当前树的本质不同子串数给一个点添加一棵子树问一个串在当前树中作为子串的出现次数Solution直接广义SAM+......
  • 力扣72-编辑距离(Java详细题解)
    题目链接:力扣72-编辑距离前情提要:因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。dp五部曲。1.确定dp数组和i下标的含义。2.确定递推公式。3.dp初始化。4.确定dp的遍历顺序。5.如果没有ac打印dp数组利于debug。每一个dp题目如果都用这五步分析清楚,那么......