首页 > 其他分享 >P5336 [THUSC2016] 成绩单

P5336 [THUSC2016] 成绩单

时间:2023-10-27 13:13:55浏览次数:40  
标签:std P5336 括号 int ++ THUSC2016 vector 成绩单 dp

这得是区间 dp。还需要限制一下值域。因此 dp 状态时 \(f_{l, r, x, y}\) 表示使 \([l, r]\) 区间所有值都处于 \([x, y]\) 的最小花费。设 \(g_{l, r} = \min\{f_{l, r, x, y} + a + b (x - y) ^ 2\}\)。

思考一个序列可以被怎么消掉。维护一个类似括号序列的东西,左右匹配的括号代表消这一段区间。维护一个栈,遇到左括号入栈,遇到空字符也入栈,遇到右括号弹栈到匹配的左括号为止。因此一个合法的消除方案可以抽象成入栈、一段后缀出栈。

因此转移时拓展右端点并枚举入栈或出栈。入栈时

\[f_{l, r, x, y} \to f_{l, r+1, \min\{x, w_{r+1}\}, \max\{w_{r+1}\}} \]

出栈时

\[f_{l, k, x, y} + g_{k+1, r+1} \to f_{l, r+1, x, y} \]

这是好的做法。

思考序列被消掉的方法,是为了寻找一个好的 dp 转移方向。dp 的限制够严了,足够把求出答案的信息囊括入内。

写记搜感觉也不错,但是要改成统计式而非贡献式。转移顺序是按 \(r\) 从小到大,\(l\) 从大到小。需要离散化,这不是重点。复杂度是 \(O(n^5)\)。

谢谢 这篇题解,感觉是最自然的一篇。但是似乎没有题解说清楚为什么要按那样子分类着转移啊。想到那个栈后,对于转移方向,会更清晰一些吧。

心路回顾:这是决策单调性吧……这个函数怎么没有四边形不等式啊……区间 dp???……\(n=50\)???

#include <bits/stdc++.h>

using LL = long long;

const LL inf = 0x3f3f3f3f3f3f3f3f;

void cmin(LL &x, LL y) { x = std::min(x, y); }

int main() {
  int n, a, b; scanf("%d %d %d", &n, &a, &b);
  std::vector<int> w(n);
  for (auto &u : w) scanf("%d", &u);
  auto s = w;
  std::sort(s.begin(), s.end());
  s.erase(std::unique(s.begin(), s.end()), s.end());
  for (auto &u : w) u = std::lower_bound(s.begin(), s.end(), u) - s.begin();
  int m = s.size();
  std::vector f(n, std::vector (n, std::vector (m, std::vector<LL> (m, inf))));
  for (int i = 0; i < n; i++)
    f[i][i][w[i]][w[i]] = 0;
  std::vector g(n, std::vector<LL> (n, inf));
  for (int r = 0; r < n; r++) 
    for (int l = r; l >= 0; l--) {
      if (r < n - 1) {
        for (int x = 0; x < m; x++) 
          for (int y = x; y < m; y++) {
            cmin(f[l][r + 1][std::min(x, w[r + 1])][std::max(y, w[r + 1])], f[l][r][x][y]);
        }
      }
      for (int x = 0; x < m; x++) 
        for (int y = 0; y < m; y++) {
          // if (f[l][r][x][y] != inf) printf("%d %d %d %d : %lld\n", l, r, x, y, f[l][r][x][y]);
          cmin(g[l][r], f[l][r][x][y] + a + 1ll * b * (s[y] - s[x]) * (s[y] - s[x]));
        }
      // printf("%d %d : %lld\n", l, r, g[l][r]);
      for (int x = 0; x < m; x++) 
        for (int y = x; y < m; y++)
          for (int k = 0; k < l; k++)
            cmin(f[k][r][x][y], f[k][l - 1][x][y] + g[l][r]);
      
    }
  printf("%lld\n", g[0][n - 1]);
}

标签:std,P5336,括号,int,++,THUSC2016,vector,成绩单,dp
From: https://www.cnblogs.com/purplevine/p/solution-P53336.html

相关文章

  • 基于Java的大学生考勤系统的设计与实现(亮点:多角色、打卡签到、请假审批、上传成绩单文
    (高校学生综合测评管理系统)三、开发环境与技术3.1MySQL数据库本课题研究研发的应用程序在数据操作过程中是难以预测的,而且常常产生变化。没有办法直接从word里写数据,这不但不安全,并且难以实现应用程序的功能。想要实现运用所需要的数据存放功能,就必定要选择专业的数据库存储软......
  • 从期中成绩单,看长城汽车加速转型的“孤峰优势”
    文|螳螂观察作者|易不二年初特斯拉的降价风波让不少车企都选择跟牌,汽车市场的价格厮杀,在上半年表现的格外激烈。但“价格内卷”之下,消费者对产品体验感与科技感的追求却日益严苛,这也使得自主、合资和外资品牌争相推出新产品、新技术提高竞争门槛,试图走出“价格内卷”的漩涡。随......
  • 第14周项目3-多科成绩单(1)(2)
    问题及代码:/**Copyright(c)2014,烟台大学计算机学院*Allrightsreserved.*文件名称:MADE64.cpp*作者:孙化龙*完成日期:2014年12月2日*版本号:v1.0**问题描述:某班不超过100名同学。用二维数组score[][4]保存同学们的高数、英语、C++成绩及总成绩(在此假设学生......
  • ShardingSphere 荣获一等奖!2022 年中国开源创新大赛成绩单公布
    ​......
  • P5336 [THUSC2016]成绩单
    题意:期末考试结束了,班主任L老师要将成绩单分发到每位同学手中。L老师共有\(n\)份成绩单,按照编号从\(1\)到\(n\)的顺序叠放在桌子上,其中编号为\(i\)的的成绩单分数为\(W_i\)。成绩单是按照批次发放的。发放成绩单时,L老师会从当前的一叠成绩单中抽取连续的一段,让这......
  • [THUSC2016]成绩单
    这个题貌似是一类套路题啊,但是我好像没有见过(;′⌒`)。我们首先要观察到一个关键性质:每次操作可以看成原序列上一个区间,且任两个区间要么不交要么包含。我们考虑最外层之间的拼接是简单的,所以不妨只考虑区间\([l,r]\)被同一个最外层区间包含的情况。倘若我们记\(dp_{l,r,v_1......
  • 2022阿里云云原生年度成绩单来了
    作者:全新出发的阿里云云原生......
  • node1_使用fs模块整理成绩单
    fs:filesystem文件系统模块是node中内置模块用于本地文件或者目录的增删改查操作直接导入即可使用constfs=require('fs')fs.readFile('./point.txt','utf-8',(er......
  • 做题记录整理dp14 P5336 [THUSC2016]成绩单(2022/9/27)
    P5336[THUSC2016]成绩单这题难度标的虚高首先一眼区间dp,然后写出递推方程然后发现爆空间,再上离散化然后就没了。。。撑死也就是蓝题不过学到了一个离散化技巧#incl......