原文链接www.cnblogs.com/zhouzhendong/p/CF1239E.html

前言

咕了这么久之后,我的博客复活了!

题解

结论1

存在一个最优解\(A\)数组,满足\(\forall 1\leq i <n, A_{1,i}\leq A_{1,i+1}, A_{2,i}\geq A_{2,i+1}\)

证明提示:假设 \(A_{1,i} > A_{1,j},i<j\),那么,交换这两个值之后得到的答案严格不劣,另一行证法相同。

结论2

当\(A\)数组满足\(\forall 1\leq i <n, A_{1,i}\leq A_{1,i+1}, A_{2,i}\geq A_{2,i+1}\)时,从左上角走到右下角存在一种方案,使得经过的权值之和最大,并且经过整个第一行或整个第二行。

证明

定义路径 \(i\) 表示经过 \(A_{1,i}\) 和 \(A_{2,i}\) 的合法路径。那么可以证明,当 \(1<i<n\) 时,路径 \(i-1\) 和路径 \(i+1\) 中至少存在一个不劣于路径 \(i\) 。

具体地,记 \(s_i\) 表示路径 \(i\) 的权值和,那么

\[s_{i+1} - s_i = A_{1,i+1} - A_{2,i}\\ s_{i-1}-s_i = A_{2,i-1} - A_{1,i}
\]

假设 \(s_i>s_{i-1},s_i>s_{i+1}\) ,那么

\[A_{1,i+1} < A_{2,i} , A_{2,i-1}<A_{1,i}
\]

又因为

\[A_{1,i}\leq A_{1,i+1}, A_{2,i}\leq A_{2,i-1}
\]

所以

\[A_{1,i}\leq A_{1,i+1}<A_{2,i}\leq A_{2,i-1}<A_{1,i}\Longrightarrow A_{1,i}<A_{1,i}
\]

矛盾,故 \(s_i\leq s_{i-1},s_i\leq s_{i+1}\) 二者至少有一个正确。

假设 \(s_i\leq s_{i-1}\) 成立,那么 \(A_{1,i}\leq A_{2,i-1}\) ,所以 \(A_{1,i-1}\leq A_{1,i}\leq A_{2,i-1}\leq A_{2,i-2}\),所以可以得到 \(s_{i-1}\leq s_{i-2}\),即

\[s_i\leq s_{i-1} \Rightarrow s_{i-1}\leq s_{i-2}
\]

于是可得 \(s_i\leq s_1\) 。

若 \(s_i\leq s_{i+1}\) ,则同理可得 \(s_i\leq s_n\) 。

综上所述,\(s_i\leq s_1,s_i\leq s_n\) 二者至少有一个正确。

所以,对于 \(1<i<n\) ,必然有 \(s_1\) 或者 \(s_n\) 不劣于 \(s_i\),所以,\(\max(s_1,s_n) = \max_{i = 1}^{n} (s_i)\) 。

于是结论2得证。

解决问题

我们现在要解决的问题变成:将最小值和次小值分别置于左上角和右下角,其余的数分成权值和尽量平均的两份,也就是最小化权值和的两部分 \(\max\) 。

由于输入的 \(a\) 数组值域较小,容易想到使用背包算法解决剩余的问题,并使用 bitset 优化,但是考虑到要记录方案,无法使用 bitset

考虑数的个数不多,我们可以采用折半的方法,每一半有 \(n-1\) 个数。对于每一半,分别暴力枚举每一个数是否被选,把所有方案状态压缩之后记到二维数组中。数组的两维分别表示选了几个数、这些数的和。

最后,再使用双指针扫描数组获取最优解即可。这部分可以参照代码理解。

代码

  1. #include <bits/stdc++.h>
  2. #define clr(x) memset(x,0,sizeof x)
  3. #define For(i,a,b) for (int i=(a);i<=(b);i++)
  4. #define Fod(i,b,a) for (int i=(b);i>=(a);i--)
  5. #define pb(x) push_back(x)
  6. #define mp(x,y) make_pair(x,y)
  7. #define fi first
  8. #define se second
  9. #define outval(x) cerr<<#x" = "<<x<<endl
  10. #define outtag(x) cerr<<"-----------------"#x"-----------------\n"
  11. #define outarr(a,L,R) cerr<<#a"["<<L<<".."<<R<<"] = ";\
  12. For(_x,L,R) cerr<<a[_x]<<" ";cerr<<endl;
  13. using namespace std;
  14. typedef long long LL;
  15. typedef unsigned long long ULL;
  16. typedef pair <int,int> pii;
  17. LL read(){
  18. LL x=0,f=0;
  19. char ch=getchar();
  20. while (!isdigit(ch))
  21. f=ch=='-',ch=getchar();
  22. while (isdigit(ch))
  23. x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
  24. return f?-x:x;
  25. }
  26. const int N=26,S=N*50000;
  27. int n,s;
  28. vector <int> a,b;
  29. bitset <S> va[N],vb[N];
  30. int sta[N][S],stb[N][S];
  31. void SolveA(int k,int cnt,int sum,int st){
  32. if (k==n-1){
  33. if (!va[cnt][sum]){
  34. va[cnt][sum]=1;
  35. sta[cnt][sum]=st;
  36. }
  37. return;
  38. }
  39. SolveA(k+1,cnt,sum,st);
  40. SolveA(k+1,cnt+1,sum+a[k],st|1<<k);
  41. }
  42. void SolveB(int k,int cnt,int sum,int st){
  43. if (k==n-1){
  44. if (!vb[cnt][sum]){
  45. vb[cnt][sum]=1;
  46. stb[cnt][sum]=st;
  47. }
  48. return;
  49. }
  50. SolveB(k+1,cnt,sum,st);
  51. SolveB(k+1,cnt+1,sum+b[k],st|1<<k);
  52. }
  53. int ans=1e9,ansa,ansb;
  54. int res[2][N];
  55. void chkans(int i,int j,int ap,int bp){
  56. int val=max(ap+bp,s-ap-bp);
  57. if (val<ans){
  58. ans=val;
  59. ansa=sta[i][ap];
  60. ansb=stb[j][bp];
  61. }
  62. }
  63. int main(){
  64. n=read();
  65. For(i,1,n*2)
  66. a.pb(read());
  67. sort(a.begin(),a.end());
  68. reverse(a.begin(),a.end());
  69. res[0][1]=a.back(),a.pop_back();
  70. res[1][n]=a.back(),a.pop_back();
  71. s=0;
  72. for (auto i : a)
  73. s+=i;
  74. For(i,1,n-1)
  75. b.pb(a.back()),a.pop_back();
  76. SolveA(0,0,0,0);
  77. SolveB(0,0,0,0);
  78. For(i,0,n-1){
  79. int j=n-1-i;
  80. vector <int> bp;
  81. For(k,0,s)
  82. if (vb[j][k])
  83. bp.pb(k);
  84. For(k,0,s){
  85. if (!va[i][k])
  86. continue;
  87. while (bp.size()>=2&&(bp[bp.size()-2]+k)*2>=s)
  88. bp.pop_back();
  89. if (bp.size()>0)
  90. chkans(i,j,k,bp.back());
  91. if (bp.size()>=2)
  92. chkans(i,j,k,bp[bp.size()-2]);
  93. }
  94. }
  95. int t0=1,t1=0;
  96. For(i,0,n-2)
  97. if (ansa>>i&1)
  98. res[0][++t0]=a[i];
  99. else
  100. res[1][++t1]=a[i];
  101. For(i,0,n-2)
  102. if (ansb>>i&1)
  103. res[0][++t0]=b[i];
  104. else
  105. res[1][++t1]=b[i];
  106. sort(res[0]+2,res[0]+n+1);
  107. sort(res[1]+1,res[1]+n);
  108. reverse(res[1]+1,res[1]+n);
  109. For(i,0,1){
  110. For(j,1,n)
  111. printf("%d ",res[i][j]);
  112. puts("");
  113. }
  114. return 0;
  115. }

Codeforces 1239E. Turtle 折半的更多相关文章

  1. codeforces 1006 F(折半搜索)

    F. Xor-Paths time limit per test 3 seconds memory limit per test 256 megabytes input standard input ...

  2. Codeforces 912 质因数折半 方格数学期望

    A B #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #d ...

  3. Codeforces#498F. Xor-Paths(折半搜索)

    time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standa ...

  4. Codeforces Round #297 (Div. 2)E. Anya and Cubes 折半搜索

    Codeforces Round #297 (Div. 2)E. Anya and Cubes Time Limit: 2 Sec  Memory Limit: 512 MBSubmit: xxx  ...

  5. Codeforces Beta Round #96 (Div. 1) C. Logo Turtle —— DP

    题目链接:http://codeforces.com/contest/132/problem/C C. Logo Turtle time limit per test 2 seconds memory ...

  6. Codeforces Round #297 (Div. 2) [ 折半 + 三进制状压 + map ]

    传送门 E. Anya and Cubes time limit per test 2 seconds memory limit per test 256 megabytes input standa ...

  7. Codeforces H. Prime Gift(折半枚举二分)

    题目描述: Prime Gift time limit per test 3.5 seconds memory limit per test 256 megabytes input standard ...

  8. Codeforces Gym 100231F Solitaire 折半搜索

    Solitaire 题目连接: http://codeforces.com/gym/100231/ Description 给你一个8*8棋盘,里面有4个棋子,每个棋子可以做一下某个操作之一: 1.走 ...

  9. CodeForces 132C Logo Turtle (记忆化搜索)

    Description A lot of people associate Logo programming language with turtle graphics. In this case t ...

随机推荐

  1. 【洛谷 P3975】 [TJOI2015]弦论(后缀自动机)

    题目链接 建出后缀自动机. T=0,每个子串算一次,否则每个子串算该子串的\(endpos\)集合大小次. 用\(f[i]\)表示结点\(i\)表示的\(endpos\)集合大小,则\(f[i]\)为 ...

  2. Matlab函数装饰器

    info.m function result_func= info(msg) function res_func =wrap(func) function varargout = inner_wrap ...

  3. foundation-cli创建项目出错的解决方案

    使用foundation-cli创建项目时,如果当前的node版本是12的话就会出现如下错误: fs.js:27 const { Math, Object } = primordials; ^ Ref ...

  4. (在客户端)https抓包解密

    (一)原理分析 https的数据包是用对称秘钥(https协议协商出来的随机数)加密后的密文. 对称秘钥在传输线路上是密文的(被非对称加密过),但是在client.server端是明文的(因为要用于加 ...

  5. 微信支付接口--超详细带注释代码--Demo

    如果本文对你有用,请爱心点个赞,提高排名,帮助更多的人.谢谢大家!❤ 如果解决不了,可以在文末进群交流. 如果对你有帮助的话麻烦点个[推荐]~最好还可以follow一下我的GitHub~感谢观看! 微 ...

  6. IDEA快速搭建WEB项目【记录篇】

    这里用的都是市面上通用的技术,而每个公司都有自己的调用方式,可以根据实际情况与业务场景不同去进行变通 三层架构: 界面层(User Interface layer).业务逻辑层(Business Lo ...

  7. Redis基于主从复制的RCE 4.x/5.x 复现

    0x00 前言 最近期末考试,博客好久没有更新了,这段时间爆了三四个洞,趁着还没去实习,抓紧复现一下,这次复现的是Redis的RCE,复现过程中也遇到很多问题,记录下来和大家分享一下 0x01 拉取镜 ...

  8. python链式对比

    参考 https://www.cnblogs.com/shanghongyun/p/10519579.html 为什么Python中“2==2>1”结果为True在Python中,你可能会发现这 ...

  9. gdb调试(二)

    继续研究gdb相关的调试技巧,话不多说进入正题: 查看运行时数据: 这个上节中已经用过了,这里就不多说了,比较简单 还是有上节中的simple.c例子,不过得稍微做一些修改为了使用这些命令: simp ...

  10. P1600 天天爱跑步[桶+LCA+树上差分]

    题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵 ...