【题解】Codeforces Round #798 (Div. 2)
本篇为 Codeforces Round #798 (Div. 2) 也就是 CF1689 的题解,因本人水平比较菜,所以只有前四题
A.Lex String
题目描述
原题面
给定两个字符串 \(a,b\),要求通过以下的两种操作构造一个新的字符串 \(c\),使得 \(c\) 的字典序最小,并且要求不能连续使用某一种操作超过 \(k\) 次
1.从 \(a\) 中任选一个字符插入到 \(c\) 的末尾
2.从 \(b\) 中任选一个字符插入到 \(c\) 的末尾
若某一个字符串为空则认为构造结束。
若字符串 \(x\) 比字符串 \(y\) 字典序小则必定满足以下两种情况之一:
1.\(x\) 为 \(y\) 的前缀,且 \(x \not= y\)
2.从左到右的顺序,\(x\) 与 \(y\) 第一个不同的位置上 \(x\) 的字符的字典序比 \(y\) 的字符的字典序小
题目分析
我们首先可以发现一点:所谓的插入末尾与插入开头并没有任何的区别
所以为了字典序小我们肯定每一次选择 \(a,b\) 中字典序最小的字符,如果超过了 \(k\) 次就选另一个字符串的,下一次再选它就好了
需要注意这里的字典序小不包含:仅仅是字符串长度更小,所以不用考虑这样的构造出的字符串长度上的问题
代码详解
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 105;
char a[MAXN],b[MAXN];
int main(){
int t;
cin>>t;
while(t--){
int n,m,k;
cin>>n>>m>>k;
for(int i=1; i<=n; i++){
cin>>a[i];
}
for(int i=1; i<=m; i++){
cin>>b[i];
}
sort(a+1,a+n+1);
sort(b+1,b+m+1);
int l = 1,r = 1,tmp = 0;
bool flag = false;
while(l <= n && r <= m){
if(a[l] < b[r]){
if(flag){
cout<<a[l++];
flag = false;
tmp = 1;
}
else{
if(tmp < k){
cout<<a[l++];
tmp++;
}
else{
cout<<b[r++];
tmp = 1;
flag = true;
}
}
}
else if(a[l] >= b[r]){
if(!flag){
cout<<b[r++];
flag = true;
tmp = 1;
}
else{
if(tmp < k){
cout<<b[r++];
tmp++;
}
else{
cout<<a[l++];
tmp=1;
flag = false;
}
}
}
}
cout<<endl;
}
return 0;
}
其实代码有一点复杂,但是其实思路很简单
B. Mystic Permutation
题目描述
原题面
给定一个 \([1,n]\) 的排列,要求你构造一个 \([1,n]\) 的排列,使得这两个排列之间的任意一个相同位置的元素都不相同,且满足这个排列的字典序最小。
如果无法构造出这样的序列则输出 -1
题目分析
一个非常正常的想法:把元素从小到大插入,如果遇到了相同的或者用过的就跳过
但是这样会出现一种情况那就是序列的最后一个元素是 \(n\),那么放到最后一个元素的时候就只剩下了 \(n\),那么就无论如何也无法放置了
这个问题也非常好解决:最后的这个元素 \(n\) 我们肯定不能放在很靠前的位置,因为这样很明显字典序不会最小了,那么为了使得这个元素放得下我们就放在 \(n-1\) 的位置上,让 \(n-1\) 的位置上原本应该放的元素放到 \(n\) 上,这样能保证前 \(n-2\) 个一定是最小的,而不存在一种别的方法使得可以使得最后的两个元素比我们现在放置的更小而且前 \(n-2\) 个依旧保持最小。
有一说一样例是真强,不然的话我应该发现不了这一点。
代码详解
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e3+5;
bool flag[MAXN];
int a[MAXN];
int main(){
int t;
cin>>t;
while(t--){
memset(flag,false,sizeof(flag));
int n;
cin>>n;
if(n == 1){
cin>>a[1];
printf("-1\n");
continue;
}
for(int i=1; i<=n; i++){
cin>>a[i];
}
for(int i=1; i<=n; i++){
if(i == n - 1 && !flag[a[n]]){
printf("%d ",a[n]);
flag[a[n]] = true;
}
for(int j=1; j<=n; j++){
if(!flag[j] && j != a[i]){
printf("%d ",j);
flag[j] = true;
break;
}
}
}
cout<<endl;
}
return 0;
}
因为数据范围比较小,所以为了写的来更加舒服就写了这样非常暴力的做法,但是我们应该理解起来更容易一些。
C. Infected Tree
题目描述
原题面
给定一棵以 \(1\) 号节点为根的二叉树,现在 \(1\) 号节点感染了病毒,病毒每一回合都会去感染与该节点直接相连的节点,而你在这一回合里可以选择删除任意一个没有被病毒感染的点,这样就断开了它与其直接相连的点得关系,询问最多可以有多少不被病毒感染的点,被删除的点不算做不被病毒感染的点
题目分析
我们考虑为了尽可能多的保留节点,我们每一次肯定是会删除被病毒感染的节点的某个子节点,而删除之后我们的问题就可以转化为它的另一个儿子(注意为二叉树)根被感染病毒能保留多少节点的子问题,那么这很明显就可以考虑一下 \(DP\)。\(DP\) 状态也很简单:\(dp[i]\) 表示以 \(i\) 为根的子树若 \(i\) 被感染病毒,最多能保留多少节点
那么下面就是考虑转移了,转移很明显就是我们考虑删除哪一个 \(i\) 的子节点就好了,因为是二叉树所以不用考虑更多的情况。那么我们就分别考虑究竟删除哪一个子节点,假设删除 \(son_1\),那么相当于在 \(son_1\) 的子树里我们可以保留下 \(size[son_1] - 1\) 个节点,\(size[i]\) 代表以 \(i\) 为根的子树的大小(包含节点 \(i\)),而在 \(son_2\) 的子树里,我们依旧可以保留下 \(dp[son_2]\) 个节点,所以最终的状态就是:
\]
需要注意可能该子树为空,那么 \(size[son] - 1\) 就是一个负数,所以需要对 \(0\) 取 \(\max\),避免这种情况
代码详解
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 3e5+5;
struct edge{
int nxt,to;
edge(){}
edge(int _nxt,int _to){
nxt = _nxt,to = _to;
}
}e[2 * MAXN];
int ans = 0,cnt,head[MAXN],dp[MAXN],sz[MAXN];
//dp[now] 表示以 now 为根的子树,假设 now 被感染,最多保留多少个
void add_edge(int from,int to){
e[++cnt] = edge(head[from],to);
head[from] = cnt;
}
void dfs(int now,int fa){
sz[now] = 1;
int son[3] = {0,0,0};
int tot = 0;
for(int i=head[now]; i;i = e[i].nxt){
int to = e[i].to;
if(to == fa) continue;
son[++tot] = to;
dfs(to,now);
sz[now] += sz[to];
}
//去 son[1] / 去 son[2]
dp[now] = max(dp[son[1]] + max(sz[son[2]] - 1,0),dp[son[2]] + max(sz[son[1]] - 1,0));
}
int main(){
int t;
cin>>t;
while(t--){
memset(head,0,sizeof(head));
memset(dp,0,sizeof(dp));
memset(sz,0,sizeof(sz));
ans = 0;
int n;
cin>>n;
for(int i=1; i<n; i++){
int from,to;
cin>>from>>to;
add_edge(from,to);
add_edge(to,from);
}
dfs(1,0);
printf("%d\n",dp[1]);
}
return 0;
}
先进行 \(dfs\) 再更新 \(sz\) 和 \(dp\),以及多组数据所以每次需要将各种数组清零,清零 \(head\) 数组也相当于清零边的数组了
D. Lena and Matrix
题目描述
原题面
给定一个 \(n\times m\) 的矩阵,每个位置都有一个颜色,分别为黑色或白色,要求你选择一个位置(不计这个位置上是什么颜色),使得整个位置到所有黑色格子的曼哈顿距离的最大值最小。
曼哈顿距离即:\(|x_1 - x_2| + |y_1 - y_2|\)
题目分析
要求的是最大值最小,其实发现这个最大值不是和任意一个黑色格子的距离都有可能成为最大值的,能成为最大距离的黑色格子一定是最左上、右下、左下、右上的黑格子,可以发现如果不是这四个格子,那么把距离转化到这四个黑色格子上都一定可以增加
下面就是如何寻找着四个黑色格子的问题了,我感觉这个思路还是很神奇的。
考虑如果一个格子离左上角越近,\(x\) 越小,\(y\) 越小,而且 \(x\) 与 \(y\) 的减小,对其离左上角的距离产生的贡献是一样的,那么就直接令这个贡献为 \(x+y\),那么最左上角的点也就一定是贡献最小的点,最右下角的点也一定是贡献最大的点,这就解决了两个。
考虑如果一个格子里右上角越近,\(x\) 越大,\(y\) 越小,而且它们产生的贡献也都是一样的,所以就考虑直接令贡献为 \(x-y\),这样最右上的点也就是 \(x-y\) 最大点,最左下的点也就是 \(x-y\) 最小的点,至此四个点全部解决了。
那么就是要找一个位置使得这个位置到这四个位置的距离最大值最小,那么就直接枚举每一个位置寻找一下就好了
代码详解
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int INF = 1e9+5;
struct node{
int x,y;
node(){}
node(int _x,int _y){
x = _x,y = _y;
}
};
int main(){
int t;
cin>>t;
while(t--){
node a[6];
bool flag[6];
memset(flag,0,sizeof(flag));
int n,m;
cin>>n>>m;
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
char h;
cin>>h;
if(h == 'B'){
if(i + j > a[1].x + a[1].y || !flag[1]) a[1] = node(i,j),flag[1] = true;
//越在右下角 i + j 越大
if(i + j < a[2].x + a[2].y || !flag[2]) a[2] = node(i,j),flag[2] = true;
//越在左上角 i + j 越小
if(i - j > a[3].x - a[3].y || !flag[3]) a[3] = node(i,j),flag[3] = true;
//越在右上角 i - j 越大
if(i - j < a[4].x - a[4].y || !flag[4]) a[4] = node(i,j),flag[4] = true;
//越在左下角 i - j 越小
}
}
}
int res = INF;
node ans;
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
int h = 0;
for(int k=1; k<=4; k++){
h = max(h,abs(i - a[k].x) + abs(j - a[k].y));
}
if(h < res){
ans = node(i,j);
res = h;
}
}
}
printf("%d %d\n",ans.x,ans.y);
}
return 0;
}
先去找四个点找到了就每个位置枚举一下,最后输出就好了
【题解】Codeforces Round #798 (Div. 2)的更多相关文章
- [题解] Codeforces Round #549 (Div. 2) B. Nirvana
Codeforces Round #549 (Div. 2) B. Nirvana [题目描述] B. Nirvana time limit per test1 second memory limit ...
- [题解]Codeforces Round #709 (Div. 1, based on Technocup 2021 Final Round) - A. Basic Diplomacy
[题目] A. Basic Diplomacy [描述] Aleksey有n个朋友,有一个m天的假期,每天都需要一个朋友来陪他.给出每天有空的朋友的编号,要求同一个朋友来的天数不能超过m/2上取整.求 ...
- [题解]Codeforces Round #254 (Div. 2) B - DZY Loves Chemistry
链接:http://codeforces.com/contest/445/problem/B 描述:n种药品,m个反应关系,按照一定顺序放进试管中.如果当前放入的药品与试管中的药品要反应,危险系数变为 ...
- [题解]Codeforces Round #254 (Div. 2) A - DZY Loves Chessboard
链接:http://codeforces.com/contest/445/problem/A 描述:一个n*m的棋盘,有一些格子不能放棋子.现在把黑白棋子往上放,要求放满且相邻格子的棋子颜色不同.输出 ...
- 题解——Codeforces Round #508 (Div. 2) T3 (贪心)
贪心的选取最优解 然后相减好 记得要开long long #include <cstdio> #include <algorithm> #include <cstring ...
- 题解——Codeforces Round #508 (Div. 2) T2 (构造)
按照题意构造集合即可 注意无解情况的判断 #include <cstdio> #include <algorithm> #include <cstring> #in ...
- 题解——Codeforces Round #508 (Div. 2) T1 (模拟)
依照题意暴力模拟即可A掉 #include <cstdio> #include <algorithm> #include <cstring> #include &l ...
- Codeforces Round #160 (Div. 1) 题解【ABCD】
Codeforces Round #160 (Div. 1) A - Maxim and Discounts 题意 给你n个折扣,m个物品,每个折扣都可以使用无限次,每次你使用第i个折扣的时候,你必须 ...
- Codeforces Round #383 (Div. 2) 题解【ABCDE】
Codeforces Round #383 (Div. 2) A. Arpa's hard exam and Mehrdad's naive cheat 题意 求1378^n mod 10 题解 直接 ...
随机推荐
- python---复杂度、斐波那切数列、汉诺塔
时间复杂度 用来估计算法运行时间的一个式子. 一般来说, 时间复杂度高的算法比复杂度低的算法慢. 常见的时间复杂度: O(1) < O(logn) < O(n) < O( ...
- Java学习day9
抽象类的关键字:abstract 类中有抽象方法时,需要在类名前也加上abstract关键字,即 public abstract class 类名{ } 同时,抽象类不能直接实例化,需要通过子类继承, ...
- Java学习day16
IO流即输入/输出流,按数据类型分为:字节流和字符流 与IO有关的操作最后都要释放,使用close方法 以字节流形式写入数据后需要换行可以添加换行符,注意旧版系统之间识别的换行符不相同,旧版Windo ...
- 分布式应用运行时 Dapr 1.7 发布
Dapr 是一个开源.可移植的.事件驱动的运行时,可以帮助开发人员构建在云和边缘上运行的弹性的.微服务的.无状态和有状态应用程序,并且关注于业务逻辑而不用考虑分布式相关的问题. 分布式相关的问题交给D ...
- pt-osc又又出现死锁了
今天使用pt-osc修改mysql表结构,又出现死锁了,老大让尽量解决这个问题,我们先分析一下pt-osc容易出现死锁的原因,再来解决这个问题. 根据pt-osc打印的日志,可以看到pt-osc执行原 ...
- ArcGIS使用技巧(四)——山体阴影
新手,若有错误还请指正! 最近在制图的时候出现如下的情况(图1),怎么调整Display的三个参数都没用. 图 1 查看其信息,发现dem的像元大小为0.00027(图2),是未投影的 图 2 查看A ...
- js实现图片懒加载原理
原理 图片懒加载是前端页面优化的一种方式,在页面中有很多图片的时候,图片加载就需要很多时间,很耗费服务器性能,不仅影响渲染速度还会浪费带宽,为了解决这个问题,提高用户体验,所以就出现了懒加载这种方式来 ...
- 操作系统深度研究(75页PPT)
上一篇:命令行版的斗地主你玩过没? 内容覆盖操作系统基本概念.分类.关键技术,体系架构,发展历程和主流国产操作系统厂商分析. 文中报告节选自兴业证券经济与金融研究院已公开发布研究报告,具体报告内容及相 ...
- DH问题汇总
本节内容主要转载于:弄清楚DL,D-H,CDH problem,CDH assumption,DDH,BDDH,BCDH. DLP(Discrete Logarithm Problem) 在乘法群\( ...
- 【python疫情可视化】用pyecharts开发全国疫情动态地图,效果酷炫!
一.效果演示 我用python开发了一个动态疫情地图,首先看下效果: 如图所示,地图根据实时数据通过时间线轮播的方式,动态展示数据的变化.随着时间的推移,疫情确诊数量的增多,地图各个省份颜色逐渐加深, ...