Codeforces Round 855 (Div. 3) E题题解

news2024/12/30 3:49:06

文章目录

  • [ Unforgivable Curse (hard version)](https://codeforces.com/contest/1800/problem/E2)
    • 问题建模
    • 问题分析
      • 方法1分析性质
        • 1.分析操作对元素位置的影响
        • 2.分析可以使用操作的元素可以与相邻元素交换位置的作用
        • 代码
      • 方法2通过DFS得到相互可以交换位置的字符集合
        • 代码
      • 方法3通过并查集连通可交换位置
        • 代码

Unforgivable Curse (hard version)

在这里插入图片描述

问题建模

给定两个字符串s和t,每次能让一个字符与其相差k或k+1个距离的字符进行交换,问能否让字符串s通过若干次该操作使其变为字符串t

问题分析

方法1分析性质

1.分析操作对元素位置的影响

使用一次该操作,可以让当前元素与另一个元素交换位置,再用一次则可以将该元素放到与之相邻的位置,再一次则可以让相邻两个元素完成交换,且不影响其余元素。

在这里插入图片描述

2.分析可以使用操作的元素可以与相邻元素交换位置的作用

对于可以使用该操作的元素,其可以与相邻元素交换位置,则所有可以使用该操作的元素之间可以通过连续使用该操作,从而可以任意交换顺序,则对于这些位置的元素只需检查两个字符串字符是否对应都有即可。而不能使用该操作的元素则需要单独比较是否对应相等

代码

#include<bits/stdc++.h>

#define x first
#define y second
#define C(i) str[0][i]!=str[1][i]
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int N =210, Mod = 998244353, P = 2048;

void solve() {
    int n,k;
    cin >>n >>k;
    string s,t;
    cin >>s >>t;
    vector<int> cnt(26,0);
    bool ok=true;
    for(int i=0;i<n;i++){
        if(i>=k||i+k<n){
            cnt[s[i]-'a']++,cnt[t[i]-'a']--;
        }else {
            ok&=(s[i]==t[i]);
        }
    }
    if(ok&&count(cnt.begin(),cnt.end(),0)==26) puts("YES");
    else puts("NO");
}

int main() {
    int t = 1;
    cin >> t;
    while (t--) solve();
    return 0;
}

方法2通过DFS得到相互可以交换位置的字符集合

每个位置一次操作可以到达的点为一个可以相互交换的集合,可以先通过DFS得到每个点所属集合。然后将两个字符串中对应位置的字符存入所在集合里,排序后形成形式同一的字符串进行比较。

代码

#include<bits/stdc++.h>

#define x first
#define y second
#define C(i) str[0][i]!=str[1][i]
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int N =2e5+10, Mod = 998244353, P = 2048;
int n,k;
int a[N];
vector<char> g[N];
int idx;
void dfs(int u,int idx){
    if(u<0||u>=n||a[u]) return ;
    a[u]=idx;///记录u点所在集合编号
    dfs(u+k,idx),dfs(u+k+1,idx),dfs(u-k,idx),dfs(u-k-1,idx);
}

string make(string str){
    for(int i=1;i<=idx;i++){
        g[i].clear();
    }
    for(int i=0;i<n;i++){
        ///将各点字符存入所属集合内
        g[a[i]].push_back(str[i]);
    }
    for(int i=1;i<=idx;i++){
        ///将各个集合内的字符排序
        sort(g[i].begin(),g[i].end());
    }
    string ans;
    ///将各个集合内的元素弄成形式统一的字符串用于比较
    for(int i=0;i<n;i++){
        ans+=g[a[i]].back();
        g[a[i]].pop_back();
    }
    return ans;
}

void solve() {
    cin >>n >>k;
    string s,t;
    cin >>s >>t;
    idx=0;
    memset(a,0,sizeof(int)*(n+1));
    for(int i=0;i<n;i++){
        if(!a[i]){
            dfs(i,++idx);
        }   
    }   
    
    if(make(s)==make(t))    puts("YES");
    else puts("NO");
}

int main() {
    int t = 1;
    cin >> t;
    while (t--) solve();
    return 0;
}

方法3通过并查集连通可交换位置

先通过并查集将每个位置可到达的位置连通,然后将连通的字符进行记录,最后比较两个字符串每个连通集内的字符。

代码

#include<bits/stdc++.h>

#define x first
#define y second
#define C(i) str[0][i]!=str[1][i]
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int N =2e5+10, Mod = 998244353, P = 2048;
int n,k;
int a[N];
int cnt[N][26];
int p[N];
int find(int x){
    if(x!=p[x]) p[x]=find(p[x]);
    return p[x];
}

void solve() {
    cin >>n >>k;
    string s,t;
    cin >>s >>t;
    for(int i=0;i<n;i++)    p[i]=i;
    for(int i=0;i<n;i++)    memset(cnt[i],0,sizeof(int)*(26));
    
    ///将可以相互到达的位置连通
    for(int i=0;i<n;i++){
        if(i+k<n){
            int fa=find(i),fb=find(i+k);
            if(fa!=fb){
                p[fa]=fb;
            }
        }
        if(i+k+1<n){
            int fa=find(i),fb=find(i+k+1);
            if(fa!=fb){
                p[fa]=fb;
            }
        }  
    }   

    for(int i=0;i<n;i++){
        ///将该位置字符记录在对应连通块内
        cnt[find(i)][s[i]-'a']++;
        cnt[find(i)][t[i]-'a']--;
    }    

    for(int i=0;i<n;i++){
        if(find(i)==i){
            ///检查该连通块内字符是否相等
            for(int j=0;j<26;j++){
                if(cnt[i][j]!=0){
                    puts("NO");
                    return ;
                }
            }
        }
    }
    puts("YES");
}

int main() {
    int t = 1;
    cin >> t;
    while (t--) solve();
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/827208.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3和typescript_组件

1 components下新建myComponent.vue 2 页面中引入组件&#xff0c;传入值&#xff0c;并且绑定事件函数。 3

原型链污染,nodejs逃逸例子

文章目录 原型链污染原型链污染原理原型链污染小例子 原型链污染题目解析第一题第二题 Nodejs沙箱逃逸方法一方法二 原型链污染 原型链污染原理 原型链 function test(){this.a test; } b new test;可以看到b在实例化为test对象以后&#xff0c;就可以输出test类中的属性a…

关于Linux启动后eth0网卡起不来的问题

1./etc/udev/rules.d/70-persistent-net.rules 先到这个文件中 将eth0注掉 ## 同时记录ADDR 2.mv /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth2 注意这个eth2, 要和第一步的号码对应 同时进入文件,将设备和ADDR修改 3.重启网络 servi…

FTP文件传输协议

FTP文件传输协议 介绍 将某台计算机中的文件通过网络传送到可能相距很远的另一台计算机中&#xff0c;是一项基本的网络应用&#xff0c;即文件传送文件传输协议(File Transfer Protocol)是因特网上使用得最广泛的文件传输协议 FTP提供交互式访问&#xff0c;允许客户指明文件…

flask中写一个基础的sqlHelper类

写一个SQLHelper类&#xff1a; from flask_sqlalchemy import SQLAlchemydb SQLAlchemy()class SQLHelper:staticmethoddef add(record):db.session.add(record)return SQLHelper.session_commit()staticmethoddef add_all(records):db.session.add_all(records)return SQLH…

FFmepg视频解码

1 前言 上一篇文章<FFmpeg下载安装及Windows开发环境设置>介绍了FFmpeg的下载安装及环境配置&#xff0c;本文介绍最简单的FFmpeg视频解码示例。 2 视频解码过程 本文只讨论视频解码。 FFmpeg视频解码的过程比较简单&#xff0c;实际就4步&#xff1a; 打开媒体流获取…

Meta-Transformer:基于Transformer的多模态感知,融合Token化与共享编码

论文标题&#xff1a;Meta-Transformer: A Unified Framework for Multimodal Learning 论文地址&#xff1a;https://arxiv.org/pdf/2307.10802.pdf 这里写目录标题 引言基于Transformer的多模态发展Meta-Transformer框架预备知识数据到序列如何分词&#xff08;Data-to-Seq…

Clion一个项目内多个main

创建单个main文件时 这样的文件不属于任何项目&#xff0c;每个文件都有自己的exe

全网最强,Jmeter接口测试-SHA256加密接口测试(详细实战)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 接口文档如下&…

【福建事业单位-语言理解】04 逻辑填空-病句-歧义

【福建事业单位-语言理解】04 逻辑填空-病句-歧义 一、逻辑填空1.1 词的辨析1.1.1词义侧重1.1.2固定搭配1.1.3程度轻重1.1.4 感情色彩总结 1.2语境分析&#xff08;关联关系&#xff09;1.2.1 转折1.2.2递进1.2.3并列1.2.4因果关系 1.3语境分析&#xff08;对应关系&#xff09…

中国工商银行长春分行 聚焦融合互促 让机关党建更有活力

党的十八大以来&#xff0c;中国工商银行长春分行党委认真落实中央部署&#xff0c;立足金融工作政治性、人民性的基本原则&#xff0c;深刻把握机关党建的要点、着力破解难点、大力打造亮点&#xff0c;围绕“党建”模式&#xff0c;将党建融入经营管理各个方面&#xff0c;使…

SSD 之乱七八糟的概念

1. 性能指标有哪些&#xff1f;分别是什么意思&#xff1f; 硬盘性能指标一般包括 IOPS&#xff08;反映的是随机读写性能&#xff09;、吞吐量&#xff08;也称为带宽&#xff0c;反映的是顺序读写性能&#xff09;、Response Time / Latency&#xff08;响应时间 / 时延&…

dev控件gridControl,gridview中添加合计

需求&#xff1a;在合并结账查询中&#xff0c;双击每一条结账出现这次结账对应的结算明细&#xff1a; 弹出的页面包括&#xff1a;结算日期&#xff0c;ID&#xff0c;姓名&#xff0c;费别&#xff0c;预交金收入&#xff0c;结算金额&#xff0c;收据号&#xff0c;合计&a…

什么是线程?为什么需要线程?和进程的区别?

目录 前言 一.线程是什么&#xff1f; 1.1.为什么需要线程 1.2线程的概念 1.3线程和进程的区别 二.线程的生命周期 三.认识多线程 总结 &#x1f381;个人主页&#xff1a;tq02的博客_CSDN博客-C语言,Java,Java数据结构领域博主 &#x1f3a5; 本文由 tq02 原创&#xf…

振动试验台使用过程中经常用到的计算公式,推荐收藏!

以下为正文&#xff1a; 1、求推力(F)的公式 式中&#xff1a; F — 推力(激振力)(N) m0 — 振动台运动部分有效质量(kg) m1 — 辅助台面质量(kg) m2 — 试件(包括夹具、安装螺钉)质量(kg) A — 试验加速度(m/s) 2、加速度(A)、速度(V)、位移(D)三个振动参数的互换运算…

Java反射全面详解

1. 什么是反射&#xff1f; 首先听这个名字就有些疑惑&#xff0c;什么是反射&#xff0c;它能用来干什么呢&#xff1f; Java官方对反射的解释是 "反射允许对封装类的字段&#xff0c;方法和构造函数进行编程式访问"。这里的字段指的就是成员变量&#xff0c;方法…

prometheus监控k8s kube-proxy target down

prometheus target down 修改配置 kubectl edit cm/kube-proxy -n kube-systemmetricsBindAddress: "0.0.0.0:10249"删除 kube-proxy pod 使之重启应用配置 kubectl delete pod --force kubectl get pod -n kube-system |grep kube-proxy|awk {print $1} -n kube-…

网工内推 | 网络安全工程师,最高15K,有高温补贴

01 超圣信华 招聘岗位&#xff1a;网络安全工程师 职责描述&#xff1a; 1. 负责网络安全产品的售前沟通交流、现状调研、方案设计、产品测试、产品选型和招投标等工作。 2. 负责网络安全集成项目的实施管理、项目交付文档编制以及项目验收等工作。 3. 负责网络安全产品的售后…

十八、Spring6集成MyBatis3.5

目录 十八、Spring6集成MyBatis3.5 18.1 实现步骤 18.2 具体实现 第一步&#xff1a;准备数据库表 第二步&#xff1a;IDEA中创建一个模块&#xff0c;并引入依赖 第三步&#xff1a;基于三层架构实现&#xff0c;所以提前创建好所有的包 第四步&#xff1a;编写pojo 第…

算法入门篇——用位运算解决一些问题

目录 1.判断一个数是2的次方数 2.统计一个数&#xff0c;它的二进制数中&#xff0c;1的个数 3.在2*&#xff08;n-1&#xff09;个数中&#xff0c;找到只出现一次的那个数 1.判断一个数是2的次方数 这个问题有好几种做法&#xff0c;但是最优雅的解法是用’位运算‘来做。…