首页 > 其他分享 >[ABC347] AtCoder Beginner Contest 347 题解

[ABC347] AtCoder Beginner Contest 347 题解

时间:2024-03-31 21:36:44浏览次数:12  
标签:AtCoder Beginner Contest int 题解 len 347 &&

[ABC347] AtCoder Beginner Contest 347 题解

A

模拟。

B

SA 模板,把所有子串丢进哈希表里即可。

C

逆天题,这个分讨并不显然。

考虑计算所有天数到今天的偏移量,然后如果最远的和最近的天数的距离 \(\le A\) 肯定可以,否则可以把所有天向右平移一段距离,然后使得最远的天到达第二周的休息日。

for(int i = 1; i <= n; i ++) {
    int d; cin >> d;
    c[i] = (d - 1) % (a + b) + 1;
    mn = min(mn, (d - 1) % (a + b) + 1);
    mx = max(mx, (d - 1) % (a + b) + 1);
}
sort(c + 1, c + n + 1);
if(mx - mn + 1 <= a) cout << "Yes";
else {
    int pos = 0;
    for(int i = 1; i <= n; i ++) {
        c[i] -= mn;
        c[i] ++;
    }
    for(int i = 1; i <= n; i ++)
        if(c[i] <= a && c[i + 1] > a) {
            pos = i;
            break;
        }
    int len = a - c[pos];
    if(c[pos + 1] + len > a + b && c[n] + len - a - b <= a) cout << "Yes";
    else cout << "No";
}

D

鉴定为比 C 简单。

考虑按位处理,如果某一位上 \(C\) 是 1,那么将剩余 \(\text{popcount}\) 更多的那个数在这位上设为 1,这样一轮枚举下来,可能会若干 \(\text{popcount}\),如果总数是奇数肯定不行,否则在每一个 \(C\) 是 0 的位置同时放两个 1,如果有剩余无解。

需要特判 0 0 0

if(n == 0 && a == 0 && b == 0) {
    cout << 0 << ' ' << 0 << '\n';
    return 0;
}
c = __builtin_popcount(n);
if(a + b < c) return cout << -1 << '\n', 0;
for(int i = 0; i < 60; i ++) {
    if(n >> i & 1) {
        if(a > b) a --, x += (1ll << i);
        else b --, y += (1ll << i);
    }
}
if(a ^ b) return cout << -1 << '\n', 0;
for(int i = 0; i < 60; i ++) {
    if(~n >> i & 1) {
        x += (1ll << i);
        y += (1ll << i);
        a --;
    }
    if(!a) break;
}
if(a) return cout << -1 << '\n', 0;
cout << x << ' ' << y << '\n';

E

如果把每个颜色表示成若干个竖直的线段(类似时间分治),那么每个位置上能得到的权值就是当时的集合大小,这个可以简单模拟计算出来,那么每个颜色的答案就是所有线段上点的和,前缀和即可。

for(int i = 1; i <= q; i ++) {
    cin >> x[i];
    if(!s.count(x[i])) s.insert(x[i]);
    else s.erase(x[i]);
    a[i] = s.size();
}
for(int i = 1; i <= q; i ++) a[i] += a[i - 1];
for(int i = 1; i <= q; i ++) {
    if(!ok[x[i]]) {
        ok[x[i]] = 1;
        b[x[i]] = i;
    }
    else {
        ans[x[i]] += a[i - 1] - a[b[x[i]] - 1];
        ok[x[i]] = 0;
    }
}
for(int i = 1; i <= n; i ++) if(ok[i]) ans[i] += a[q] - (b[i] ? a[b[i] - 1] : 0);

F

考虑分成 6 种情况讨论。

img

这六种情况覆盖了所有三个正方形之间的关系,然后需要做的就是每种情况分讨,然后二位前缀和随便搞一下就好了。

// a, b, c, d 表示左上、右上、左下、右下的矩形最大值
for(int i = 1; i <= n; i ++)
    for(int j = 1; j <= m; j ++)
        g[i][j] += (g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1]);
n = n - k + 1, m = m - k + 1;
for(int i = 1; i <= n; i ++)
    for(int j = 1; j <= m; j ++)
        s[i][j] = (g[i + k - 1][j + k - 1] - g[i - 1][j + k - 1] - g[i + k - 1][j - 1] + g[i - 1][j - 1]);
for(int i = 1; i <= n; i ++)
    for(int j = 1; j <= m; j ++)
        a[i][j] = max(max(s[i][j], a[i - 1][j]), a[i][j - 1]);
for(int i = 1; i <= n; i ++)
    for(int j = m; j; j --)
        b[i][j] = max(max(s[i][j], b[i - 1][j]), b[i][j + 1]);
for(int i = n; i; i --)
    for(int j = 1; j <= m; j ++)
        c[i][j] = max(max(s[i][j], c[i + 1][j]), c[i][j - 1]);
for(int i = n; i; i --)
    for(int j = m; j; j --)
        d[i][j] = max(max(s[i][j], d[i + 1][j]), d[i][j + 1]);
for(int i = 1; i <= n; i ++)
    for(int j = 1; j <= m; j ++) {
        cm[j] = max(cm[j], s[i][j]);
        rm[i] = max(rm[i], s[i][j]);
    }
for(int i = k; i <= m; i ++)
    ans = max(ans, cm[i] + a[n][i - k] + b[n][i + k]);
for(int i = k; i <= n; i ++)
    ans = max(ans, rm[i] + b[i - k][1] + d[i + k][1]);
for(int i = k; i <= n; i ++) {
    for(int j = k; j <= m; j ++) {
        ans = max(ans, b[n][j] + c[i][j - k] + a[i - k][j - k]);
        ans = max(ans, b[i - k + 1][1] + d[i + 1][j] + c[i + 1][j - k]);
        ans = max(ans, a[n][j - k + 1] + d[i][j + 1] + b[i - k][j + 1]);
        ans = max(ans, d[i][1] + b[i - k][j] + a[i - k][j - k]);
    }
}

G

摸了,学完网络流再补。

总结

C 罚时吃饱了,所以以后交之前应该思考一些corner case,WA了之后要仔细想一下哪里漏了。

F 没切出来,主要是没见过这种套路,这次记住就好了,对于这种情况少的可以考虑元素之间的关系。

本场亮点在于跳 C 切 D。

标签:AtCoder,Beginner,Contest,int,题解,len,347,&&
From: https://www.cnblogs.com/MoyouSayuki/p/18107303

相关文章

  • CF1942E Farm Game 题解
    我们先默认第一头牛是John的,另一种情况本质相同,最后答案乘上\(2\)就可以了。先说结论:我们将相邻两头牛配对,那么最终答案即满足至少一对牛间隔了奇数个空位的方案数。证明很简单,分\(3\)种情况讨论:每对牛间都间隔了奇数个空位。那么John开始时让所有牛往右行动,在Nhoj行......
  • [题解]P2516 [HAOI2010] 最长公共子序列——求LCS个数
    P2516[HAOI2010]最长公共子序列总的来说,这道题确实很精妙,难度也不小,耗费了不少时间去调。本来想过用容斥的思想,却因为当时理解不深没有继续思考就放弃了。学会了思路后对\(LCS\)有了更深层次的理解。题意简述给定\(A,B\)两个字符串(以.结尾),求它们的最长公共子序列的长度和个数......
  • 0324-0331题解反思
    最近我突然发现,写题解是常常会遗忘的,然而题目中的一些技巧才是永恒的,那么接下来的题解,我应该对以前的题目含有的这些技巧进行一些深刻的复盘。知识点模块1.当我们要实现一个图形的字符串的倒置,比如把福倒过来,我们可以进行以下的操作:先进行行的交换,在进行列的倒置,我们需要用到s......
  • 【C++实验1】学生成绩信息管理系统题解
    【问题描述】编写一个基于结构体得学生成绩信息管理系统。主要功能如下:1.用结构体存放所有数据。2.每个功能都用函数实现。3.输入10个学生的学号和三门课程的成绩。4.计算每个学生的总分。5.按总分从高到低排序。6.加上名次一列。7.输出最后的二维表格样式的成......
  • 题解 P9981 [USACO23DEC] Minimum Longest Trip G
    【洛谷专栏】题意\(N\)个点\(M\)条边的有向无环图,对于每一个点\(i\)你需要求出一条从\(i\)出发的最长路径且路径上边权组成的序列字典序最小。求每一条路径的长度和边权和。分析最长的路径很好求,在DAG上拓扑排序后动态规划即可。(具体的实现可以参考OI-Wiki)现在的......
  • Minlexes题解
    \(\texttt{ProblemLink}\)简要题意在一个字符串\(s\)中,对于每个后缀,任意删掉一些相邻的相同的字符,使得字符串字典序最小。注意:删掉之后拼起来再出现的相邻相同字符不能够删除。思路倍增好题。发现存在局部最优解(最优子结构),并且可以转移到其它结点,可以考虑使用dp。那就......
  • Tomcat启动失败,窗口一闪而过问题解决
    在启动Tomcat时窗口一闪而过,解决方法:在Tomcat安装目录\bin下启动cmd,或在C盘启动后跳转到Tomcat安装目录\bin,输入startup.bat(一定要先做这步,确保具体问题,再根据具体问题百度,不然又是配置JRE,又是配置Tomcat环境变量,最后做了无用功),如果显示如下:先确保java环境变量没问题,我的java......
  • 题解:AT_arc175_b [ARC175B] Parenthesis Arrangemen
    前言警示后人:字符串最大长度为\(65535\),会\(RE\)!!!\(10^7\)会爆栈!!!题意给出一个括号序列\(s\),有两种操作方式,交换两个字符需要花费\(A\),直接修改一个字符需要花费\(B\),求使这个序列合法需要的最小花费。分析我们可以先将\(s\)中能匹配的括号序列消除掉(即括号匹配......
  • [蓝桥杯] 管道 java题解
    importjava.util.*;/***管道*其实这道题核心根本不用管管道左边的如何,我们可以把左边当成注水口*/publicclassMain{staticintn;staticint[][]pipes;//阀门安排的地方staticintlen;//管道长度publicstaticvoidmain(String[]a......
  • AtCoder Beginner Contest 347 A-F 题解
    A-DivisibleQuesiton给你正整数\(N\)和\(K\),以及长度为\(N\)的序列\(A\)。提取\(A\)中所有是\(K\)倍数的元素,除以\(K\),并打印商。Solution判断\(A_i\%K\)的值是否为\(0\),如果非\(0\)则表示可以整除Code#include<bits/stdc++.h>usingnamespacest......