题面戳这里


A. Diana and Liana

首先如果s>ks>ks>k一定无解,特判一下。那么我们考虑找恰好满足满足题目中的要求的区间[l,r][l,r][l,r],那么需要要删去的数一定是(l−1)%k+max((r−l+1)−k,0)(l-1)\%k+max((r-l+1)-k,0)(l−1)%k+max((r−l+1)−k,0)。前面的表示要把[1,l−1][1,l-1][1,l−1]区间删成kkk的倍数,后面的表示要把这个区间删到kkk长度以内。判断这个值是否不大于能够删的最大值m−n⋅km-n\cdot km−n⋅k,然后更新答案。

不能枚举,但是当lll增大,恰好满足条件的区间的rrr一定也会增大。那么就枚举左端点,右端点向右移动就行了。

CODE

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 500005;
  4. int m, n, k, s, a[MAXN], b[MAXN], mx;
  5. int cnt[MAXN], need[MAXN], now, all, sum;
  6. int main () {
  7. scanf("%d%d%d%d", &m, &k, &n, &s); mx = m-n*k;
  8. if(s > k) return puts("-1"), 0;
  9. for(int i = 1; i <= m; ++i) scanf("%d", &a[i]);
  10. for(int i = 1; i <= s; ++i) {
  11. scanf("%d", &b[i]);
  12. if(++need[b[i]] == 1) ++all;
  13. }
  14. int r = 0;
  15. for(int i = 1; i <= m && r <= m; ++i) {
  16. int tmp = (i-1)%k;
  17. while(now < all && r < m) {
  18. ++cnt[a[++r]];
  19. if(cnt[a[r]] == need[a[r]]) ++now;
  20. }
  21. if(now == all && tmp + max(r-i+1-k, 0) <= mx) {
  22. printf("%d\n", tmp + max(r-i+1-k, 0));
  23. for(int j = 1; j <= tmp; ++j)
  24. printf("%d ", j);
  25. int left = max(r-i+1-k, 0);
  26. for(int j = i; j <= r && left; ++j)
  27. if(cnt[a[j]] > need[a[j]]) {
  28. --left; --cnt[a[j]];
  29. printf("%d ", j);
  30. }
  31. return 0;
  32. }
  33. if(--cnt[a[i]] == need[a[i]]-1) --now;
  34. }
  35. puts("-1");
  36. }

B. Once in a casino

直接从左到右考虑,假设前面的位置都已经满足了,那么这位上的数需要加几/减几就直接加/减上去,但是这样有可能让下一位加到9以上或者减到0以下,暂时先不管。如果到最后an≠bna_n=\not b_nan​≠​bn​就无解,反之一定有解(显然)。然后因为只要求输出前10510^5105次,模拟操作即可:直接从左到右贪心执行操作,遇到越界的情况就递归就行了。

代码挺丑的,能过就行。

CODE

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 100005;
  4. int n, A[MAXN], cur;
  5. long long ans;
  6. char a[MAXN], b[MAXN];
  7. inline int ff(int x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }
  8. inline bool chkout(int x) { return !(x >= 0 && x <= 9); }
  9. void solve(int i, int val) { //solve(i,val)表示把i加上val
  10. if(cur == 100000) return;
  11. //if(i > n) return;
  12. int k = ff(val);
  13. if(chkout(A[i+1]+val)) {
  14. if(A[i+1]+val > 9) solve(i+1, 9-(A[i+1]+val));
  15. else solve(i+1, 0-(A[i+1]+val));
  16. }
  17. if(cur == 100000) return;
  18. while(val) {
  19. ++cur;
  20. printf("%d %d\n", i, k);
  21. val -= k, A[i] += k, A[i+1] += k;
  22. if(cur == 100000) return;
  23. }
  24. }
  25. int main () {
  26. scanf("%d", &n);
  27. scanf("%s", a+1);
  28. scanf("%s", b+1);
  29. for(int i = 1; i <= n; ++i)
  30. A[i] = a[i]-'0';
  31. for(int i = 1; i <= n; ++i) {
  32. A[i+1] += b[i]-'0'-A[i];
  33. ans += abs(b[i]-'0'-A[i]);
  34. A[i] = b[i]-'0';
  35. }
  36. if(A[n+1]) puts("-1");
  37. else {
  38. printf("%I64d\n", ans);
  39. for(int i = 1; i <= n; ++i)
  40. A[i] = a[i]-'0';
  41. for(int i = 1; i <= n && cur < 100000; ++i)
  42. solve(i, b[i]-'0'-A[i]);
  43. }
  44. }

C. Compress String

直接预处理出来每两个位置的后缀的最长公共前缀记作mx[i][j]mx[i][j]mx[i][j],因为是500050005000,O(n2)dpO(n^2)dpO(n2)dp就行了(也可以SASASA)。

定义f[i]=max⁡j&lt;imx[i][j]f[i]=\max_{j&lt;i} mx[i][j]f[i]=maxj<i​mx[i][j],dp[i]dp[i]dp[i]表示到前iii个最小费用,O(n2)O(n^2)O(n2)转移很显然:

dp[i]=min(dp[i−1]+a , min⁡f[j]≥(i−j+1), j≤idp[j−1] + b)dp[i]=min(dp[i-1]+a\ ,\ \min_{f[j]\ge (i-j+1),\ j\le i} dp[j-1]\ +\ b)dp[i]=min(dp[i−1]+a , f[j]≥(i−j+1), j≤imin​dp[j−1] + b)

也有trietrietrie树/SAMSAMSAM的算法

CODE

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 5005;
  4. int n, a, b, dp[MAXN], mx[MAXN][MAXN], f[MAXN];
  5. char s[MAXN];
  6. int main () {
  7. scanf("%d%d%d", &n, &a, &b);
  8. scanf("%s", s+1);
  9. for(int i = n; i; --i) {
  10. for(int j = n; j; --j) {
  11. if(s[i] == s[j]) mx[i][j] = mx[i+1][j+1] + 1;
  12. f[i] = max(f[i], min(mx[i][j], i-j));
  13. }
  14. }
  15. dp[1] = a;
  16. for(int i = 2; i <= n; ++i) {
  17. dp[i] = dp[i-1] + a;
  18. for(int j = 2; j <= i; ++j) {
  19. if(f[j] >= i-j+1)
  20. dp[i] = min(dp[i], dp[j-1] + b);
  21. }
  22. }
  23. printf("%d\n", dp[n]);
  24. }

D. Power Tree

树形dpdpdp

定义dp[u][0]dp[u][0]dp[u][0]表示uuu子树内节点全部统一成一个值且此值可控

定义dp[u][1]dp[u][1]dp[u][1]表示uuu子树内节点全部统一成一个值且此值不可控

转移如下:

dp[u][1]=min(∑v∈Sdp[v][0]+dp[w][1](w∉S))dp[u][1]=min\left(\sum_{v\in S} dp[v][0]+dp[w][1](w\in\not S)\right)dp[u][1]=min(v∈S∑​dp[v][0]+dp[w][1](w∉​S))

dp[u][0]=min(∑dp[v][0] ,dp[u][1]+c[u])dp[u][0]=min\left(\sum dp[v][0]\ ,dp[u][1]+c[u]\right)dp[u][0]=min(∑dp[v][0] ,dp[u][1]+c[u])

答案就是dp[1][0]dp[1][0]dp[1][0]

要求哪些可能被占领就再dfs一遍就行了。我的写法记忆化了一下。

总时间复杂度O(n)O(n)O(n)

CODE

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 200005;
  4. int n, c[MAXN];
  5. vector<int>G[MAXN];
  6. long long f[MAXN][2];
  7. void dfs(int u, int ff) {
  8. if(G[u].size() == 1 && u != 1) { //注意判根
  9. f[u][0] = c[u];
  10. f[u][1] = 0;
  11. return;
  12. }
  13. long long tmp = 1ll<<60, sum = 0;
  14. for(auto v : G[u])
  15. if(v != ff) {
  16. dfs(v, u);
  17. sum += f[v][0];
  18. tmp = min(tmp, f[v][1]-f[v][0]);
  19. }
  20. //printf("%I64d\n", sum);
  21. f[u][1] = tmp + sum;
  22. f[u][0] = min(sum, f[u][1] + c[u]);
  23. }
  24. bool can[MAXN], vis[MAXN][2];
  25. void dfs2(int u, int tp, int ff) {
  26. if(vis[u][tp]) return; //记忆化
  27. vis[u][tp] = 1;
  28. if(G[u].size() == 1 && u != 1) { //注意判根
  29. if(tp == 0)
  30. can[u] = 1;
  31. return;
  32. }
  33. long long tmp = 1ll<<60, sum = 0;
  34. for(auto v : G[u])
  35. if(v != ff) {
  36. sum += f[v][0];
  37. tmp = min(tmp, f[v][1]-f[v][0]);
  38. }
  39. //f[u][1] = tmp + sum;
  40. //f[u][0] = min(sum, f[u][1] + c[u]);
  41. if(tp == 0) {
  42. if(f[u][0] == f[u][1] + c[u]) {
  43. can[u] = 1;
  44. int cnt = 0; //如果 cnt>1 两个儿子都可能被选中成为f[w][1], 那么大家都可能被选作f[v][0]
  45. for(auto v : G[u])
  46. if(v != ff) if(f[v][1]-f[v][0] == tmp) dfs2(v, 1, u), ++cnt;
  47. for(auto v : G[u])
  48. if(v != ff && (cnt > 1 || f[v][1]-f[v][0] != tmp))
  49. dfs2(v, 0, u);
  50. }
  51. if(f[u][0] == sum) {
  52. for(auto v : G[u])
  53. if(v != ff) dfs2(v, 0, u);
  54. }
  55. }
  56. else {
  57. int cnt = 0;
  58. for(auto v : G[u])
  59. if(v != ff) if(f[v][1]-f[v][0] == tmp) dfs2(v, 1, u), ++cnt;
  60. for(auto v : G[u])
  61. if(v != ff && (cnt > 1 || f[v][1]-f[v][0] != tmp))
  62. dfs2(v, 0, u);
  63. }
  64. }
  65. int main () {
  66. scanf("%d", &n);
  67. for(int i = 1; i <= n; ++i)
  68. scanf("%d", &c[i]);
  69. for(int i = 1, x, y; i < n; ++i)
  70. scanf("%d%d", &x, &y),
  71. G[x].push_back(y),
  72. G[y].push_back(x);
  73. dfs(1, -1);
  74. printf("%I64d ", f[1][0]);
  75. dfs2(1, 0, -1);
  76. int ans = 0;
  77. for(int i = 1; i <= n; ++i)
  78. if(can[i]) ++ans;
  79. printf("%d\n", ans);
  80. for(int i = 1; i <= n; ++i)
  81. if(can[i]) printf("%d ", i);
  82. }

E. The very same Munchhausen

考虑是否能拆位处理:

低位到高位枚举,设f[x][i][j][0/1]f[x][i][j][0/1]f[x][i][j][0/1]表示枚举到第xxx位,前x−1x−1x−1位构成的数×a×a×a后累积到当前位的需要加上的值为iii,前x−1x−1x−1位构成的数×a×a×a的数位之和×a×a×a与前x−1x−1x−1个数位之和的差为jjj,是否所有数位均为000时的状态是否合法。

f[x][i][j][0/1]=1f[x][i][j][0/1]=1f[x][i][j][0/1]=1表示当前状态合法,f[x][i][j][0/1]=0f[x][i][j][0/1]=0f[x][i][j][0/1]=0表示不合法。

观察转移可以发现:

xxx这一维可以省略

求解f[i][j][0/1]f[i][j][0/1]f[i][j][0/1]可以转成0−90−90−9枚举当前位向外bfsbfsbfs

答案状态即f[0][0][1]f[0][0][1]f[0][0][1],为输出答案,记录dig[i][j][0/1]dig[i][j][0/1]dig[i][j][0/1]表示最高位的值(0−90−90−9),pre[i][j][0/1]pre[i][j][0/1]pre[i][j][0/1]三元组表示状态f[i][j][0/1]f[i][j][0/1]f[i][j][0/1]的前驱。

计算得到i≤1000i≤1000i≤1000

而−1000≤j≤1000−1000≤j≤1000−1000≤j≤1000(并不会证明),从而保证了复杂度。

CODE

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int K = 1000;
  4. struct node { int x, y, z; }pre[1005][2005][2];
  5. queue<node>q;
  6. int a, dig[1005][2005][2];
  7. bool vis[1005][2005][2];
  8. inline string solve() {
  9. vis[0][K][0] = 1;
  10. dig[0][K][0] = -1;
  11. q.push({0, K, 0});
  12. while(!q.empty()) {
  13. int i = q.front().x, j = q.front().y, tp = q.front().z;
  14. if(i == 0 && j == K && tp == 1) {
  15. string re = ""; node tmp;
  16. while(~dig[i][j][tp]) {
  17. if(!re.empty() || dig[i][j][tp])
  18. re += dig[i][j][tp]+'0';
  19. tmp = pre[i][j][tp];
  20. i = tmp.x, j = tmp.y, tp = tmp.z;
  21. }
  22. return re;
  23. }
  24. for(int k = 0; k < 10; ++k) {
  25. int x = (i + k * a) / 10;
  26. int y = (i + k * a) % 10 * a + j - k;
  27. int z = (tp || k);
  28. if(y >= 0 && y <= 2000 && !vis[x][y][z])
  29. vis[x][y][z] = 1, dig[x][y][z] = k, pre[x][y][z] = q.front(), q.push({x, y, z});
  30. }
  31. q.pop();
  32. }
  33. return "-1";
  34. }
  35. int main () {
  36. scanf("%d", &a);
  37. cout<<solve()<<endl;
  38. }

F. Secret Letters

实在无力写了,自己看这里

CODE

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 100005;
  4. int n, c, d, t[MAXN], tp[MAXN];
  5. int main () {
  6. scanf("%d%d%d", &n, &c, &d);
  7. char ss[2];
  8. for(int i = 0; i < n; ++i) {
  9. scanf("%d%s", &t[i], ss);
  10. tp[i] = ss[0] == 'P' ? 0 : 1;
  11. }
  12. scanf("%d", &t[n]);
  13. int last; tp[n] = -1;
  14. long long s = 0, ans = 1ll * n * d;
  15. for(int i = n; i; --i) {
  16. if(tp[i-1] != tp[i]) last = t[i]; //i=n 时一定会执行这一条, 把last设为t[n]
  17. else s += min(1ll*d, 1ll*(last-t[i])*c);
  18. ans = min(ans, s + 1ll * (i-1) * d + 1ll*(t[n]-t[i-1]) * c);
  19. //s指后面i...n的代价 (i-1)d 指 0...i-2 直接送的代价 后面这一坨是i-1贯穿整过程的代价
  20. }
  21. printf("%I64d\n", ans);
  22. }

Codeforces Round #543 (Div. 1, based on Technocup 2019 Final Round) 题解的更多相关文章

  1. Codeforces Round #543 (Div. 2, based on Technocup 2019 Final Round)

    A. Technogoblet of Fire 题意:n个人分别属于m个不同的学校 每个学校的最强者能够选中 黑客要使 k个他选中的可以稳被选 所以就为这k个人伪造学校 问最小需要伪造多少个 思路:记 ...

  2. cf 20190307 Codeforces Round #543 (Div. 2, based on Technocup 2019 Final Round)

    B. Mike and Children time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  3. Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2)

    Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2) #include <bits/stdc++ ...

  4. (AB)Codeforces Round #528 (Div. 2, based on Technocup 2019 Elimination Round

    A. Right-Left Cipher time limit per test 1 second memory limit per test 256 megabytes input standard ...

  5. Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2) D. Minimum path

    http://codeforces.com/contest/1072/problem/D bfs 走1步的最佳状态 -> 走2步的最佳状态 -> …… #include <bits/ ...

  6. Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2) D. Minimum path(字典序)

    https://codeforces.com/contest/1072/problem/D 题意 给你一个n*n充满小写字母的矩阵,你可以更改任意k个格子的字符,然后输出字典序最小的从[1,1]到[n ...

  7. Codeforces Round #528 (Div. 2, based on Technocup 2019 Elimination Round 4) C. Connect Three 【模拟】

    传送门:http://codeforces.com/contest/1087/problem/C C. Connect Three time limit per test 1 second memor ...

  8. Codeforces Round #512 (Div. 2, based on Technocup 2019 Elimination Round 1) C. Vasya and Golden Ticket 【。。。】

    任意门:http://codeforces.com/contest/1058/problem/C C. Vasya and Golden Ticket time limit per test 1 se ...

  9. Codeforces Round #468 (Div. 2, based on Technocup 2018 Final Round)B. World Cup

    The last stage of Football World Cup is played using the play-off system. There are n teams left in ...

随机推荐

  1. 关闭iTunes自动同步

    方法步骤: 仅对iTunes安装在默认路径的生效. 在「运行」里边先后输入以下两条命令: "C:\Program Files\Common Files\Apple\Apple Applica ...

  2. Appium移动端自动化测试--元素操作与触摸动作

    常见自动化动作支持 click sendKeys swipe touch action 元素操作 1.click()点击操作 也可以用tab实现点击操作 driver.find_element_by_ ...

  3. flask使用tablib导出excel数据表

    在网页中常常有导出数据的需求,尤其是一下管理类平台.在flask中要导出excel数据表,通常可以使用xlwt库,创建文件并逐行写入数据,但是使用起来总是感觉很麻烦.tablib库相对操作更加方便. ...

  4. flask返回自定义的Response

    from json import dumps from flask import Response from flask_api import status from protocol.errors_ ...

  5. maftools | 从头开始绘制发表级oncoplot(瀑布图)

    本文首发于微信公众号 **“ 生信补给站 ”** ,期待您的关注!!! 原文链接:https://mp.weixin.qq.com/s/G-0PtaoO6bYuhx_D_Rlrlw 对于组学数据的分析 ...

  6. (十)Activitivi5之启动流程/完成任务的时候设置流程变量

    一.启动流程的时候设置流程变量 1.1 案例 /** * 启动流程实例 */ @Test public void start() { Student student=new Student(); st ...

  7. eclipse智能提示报错(to avoid the message, disable the...)

    然后这里可能会再报别的错误  我的做法是   再重新将 code recommenders 打开 ********************************** 为什么会出现 这样错误呢 ? 简 ...

  8. [JZOJ100019]A--dfn序+扫描线

    [JZOJ100019]A--dfn序+扫描线 题目链接 太懒了自行搜索 分析 这道题查了一个下午的错,真的心态崩了 不过这道题确实妙啊 类比于喝喝喝,我们发现任何一条覆盖了非法路径的路径一定不合法, ...

  9. restTemplate源码解析(一)构造restTemplate的Bean实例

    所有文章 https://www.cnblogs.com/lay2017/p/11740855.html 正文 构造一个restTemplate的Bean实例很容易,只需这样配置 @Bean publ ...

  10. Linux Centos7配置mysql8.0数据库

    本文转至:672530440 在此感谢博主,撒花!!! 本文主要从以下几个方面对自己在centos7 下安装mysql8过程做如下总结: CentOS7 安装mysql8 步骤: window下的Na ...