P8796 [蓝桥杯 2022 国 AC] 替换字符

news/2025/1/19 14:25:14/文章来源:https://www.cnblogs.com/zzzsacmblog/p/18679554

链接:https://www.luogu.com.cn/problem/P8796
题目大意:
给出原字符串,给出修改区间,每步把区间中的a字符变为b字符。求最后的字符串是什么样子的。
思路:
很显然是线段树:区间修改。然后给每个添加上26容量的数组,代替键值对的作用。接着套模板就行。
注意的思路:先后区别,同一字符多次修改。实际上就是直接修改当前目标字符就行,然后必须往下传递。
但是不能AC代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<string.h>
#include<string>
#include<vector>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
#define int long long
const int N = 1e5 + 10;
const int INF = -1;
int tag[N << 2][26];
int rf[26];
string s;
int n;
int ls(int p) { return p << 1; }
int rs(int p) { return p << 1 | 1; }void addtag(int p, int pl, int pr, int from,int to)
{//改,加上tag的作用//for (int i = 0; i < 26; i++)rf[i] = tag[p][i];for (int i = 0; i < 26; i++){if (tag[p][i] == from)tag[p][i] = to;}if (tag[p][from - 'a'] == INF)tag[p][from - 'a'] = to;
}
//顺应上到下的先后顺序
void addtagMore(int p, int pl, int pr, int*to)
{memset(rf, INF, sizeof(rf));for (int i = 0; i < 26; i++)rf[i] = tag[p][i];for (int i = 0; i < 26; i++){for (int j = 0; j < 26; j++)if (rf[i] == j+'a' and to[j]!=INF)tag[p][i] = to[j];//i+97if (rf[i] == INF)tag[p][i] = to[i];}}
void push_down(int p, int pl, int pr)
{int mid = (pl + pr) >> 1;addtagMore(ls(p), pl, mid,  tag[p]);addtagMore(rs(p), mid + 1, pr, tag[p]);memset(tag[p], INF, sizeof(tag[p]));}void update(int L, int R, int p, int pl, int pr, int from,int to)
{if (L <= pl and pr <= R){addtag(p, pl, pr, from,to);return;}push_down(p, pl, pr);int mid = (pl + pr) >> 1;if (L <= mid)update(L, R, ls(p), pl, mid, from,to);if (R > mid)update(L, R, rs(p), mid + 1, pr, from,to);}void query(int p, int pl, int pr)
{if (pl == pr){if (tag[p][s[pl-1] - 'a']!=INF)cout<< (char)tag[p][s[pl-1] - 'a'];else cout<<s[pl-1];return;}push_down(p, pl, pr);string res;int mid = (pl + pr) / 2;if (pl <= mid)query(ls(p), pl, mid);if (pr > mid) query(rs(p), mid + 1, pr);
}signed main()
{IOS;memset(tag, INF, sizeof(tag));cin >> s; n = s.length();int times; cin >> times;for (int i = 0; i < times; i++){int a, b; char c, d; cin >> a >> b >> c >> d;update(a, b, 1, 1, n, c, d);}query( 1, 1, n);return 0;}

这种就是纯按照模板写的,可能是函数调用的过程增加了时间开销。所以参考题解区的核心代码:

for (int i = 0; i < 26; i++)
{tag[ls(p)][i] = tag[p][tag[ls(p)][i]];//类似于f(f(x))键值对查找的方法tag[rs(p)][i] = tag[p][tag[rs(p)][i]];
}

这样写就很巧妙。
所以AC代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<string.h>
#include<string>
#include<vector>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
#define int long long
const int N = 1e5 + 10;
int tag[N << 2][26];
string s;
int n;
int ls(int p) { return p << 1; }
int rs(int p) { return p << 1 | 1; }
void init()
{for (int i = 0; i < N << 2; i++)for (int j = 0; j < 26; j++)tag[i][j] = j;
}
void update(int p, int pl, int pr, int L, int R, int from, int to)
{if (L<=pl and pr<=R){for (int i = 0; i < 26; i++)if (tag[p][i] == from)tag[p][i] = to;return;}int mid = (pl + pr) / 2;for (int i = 0; i < 26; i++){tag[ls(p)][i] = tag[p][tag[ls(p)][i]];//类似于f(f(x))键值对查找的方法tag[rs(p)][i] = tag[p][tag[rs(p)][i]];}for (int i = 0; i < 26; i++)tag[p][i] = i;if(L<=mid)update(ls(p), pl, mid, L, R, from, to);if(R>mid)update(rs(p), mid + 1, pr, L, R, from, to);
}
void query(int p, int pl, int pr)
{if (pl == pr){char ans = tag[p][s[pl] - 97] + 'a';cout << ans;return;}for (int i = 0; i < 26; i++){tag[ls(p)][i] = tag[p][tag[ls(p)][i]];//类似于f(f(x))键值对查找的方法tag[rs(p)][i] = tag[p][tag[rs(p)][i]];}for (int i = 0; i < 26; i++)tag[p][i] = i;int mid = (pl + pr) / 2;query(ls(p), pl, mid);query(rs(p), mid+1, pr);}
signed main()
{IOS;init();cin >> s; s = "0" + s;int times; n = s.length()-1;cin >> times;for (int i = 0; i < times; i++){int a, b;char c, d; cin >> a >> b >> c >> d;update(1, 1, n, a, b, c - 97, d - 97);}query(1, 1, n);return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

聊一聊 操作系统蓝屏 c0000102 的故障分析

一:背景 1. 讲故事 今年以来不知道为啥总有些朋友加我微信,让我帮忙分析下操作系统蓝屏问题,我也觉得挺好奇的,就问了其中一位朋友,说是B站来的,我就在拼命回忆,为啥会找我分析蓝屏?突然想到了去年好像录了一集关于 CrowdStrike 的热点事件。。。我本来是做.NET程序的故…

4-01-(C++类 this指针)

结构体传参,传递的是副本 结构体里面写函数,结构体的大小不变 函数的地址不在结构体里面。 类里面的函数都要传一个this指针,即 lea ecx,[s] 普通的函数结构体传参 this指针的特点 1、你用或者不用,它就在那里 2、参数个数确定的时候,用ecx来传递 3、参数个数不确…

协议通道版iMessage蓝号检测,iMessages数据筛选,无痕检测是否开启iMessage服务

一、实现iMessage数据检测的两种方式:1.人工筛选,将要验证的号码输出到文件中,以逗号分隔。再将文件中的号码粘贴到iMessage客户端的地址栏,iMessage客户端会自动逐个检验该号码是否为iMessage账号,检验速度视网速而定。红色表示不是iMessage账号,蓝色表示iMessage账号。2…

【开源】一款功能全面的商用级溯源防伪系统,适用于各种溯源场景

项目介绍 HiPi是一款开源、功能全面的商用级溯源防伪系统,一物一码系统,适用于各种溯源场景的大、中、小、微规模企业。系统能够追踪记录产品的生命周期各个环节,并将产品信息保存在系统中,实现品牌保护、产品营销、防止假冒伪劣产品、防窜货、产品追踪溯源等功能。 应用场…

行为分析智能监测摄像机

行为分析智能监测摄像机具有高效的行为识别和分类能力。通过摄像头捕捉到目标区域内的行为活动,并通过预先训练好的机器学习算法进行识别和分类,可以准确地分析出不同的行为特征,例如跌倒、打架等,并及时发出警报或提醒相关管理人员。这种高效的行为识别能力可以帮助监控中…

秸秆焚烧自动监测摄像机

秸秆焚烧自动监测摄像机具有高效的监测和识别能力。通过摄像头捕捉到秸秆焚烧的情况,并通过预先训练好的机器学习算法进行识别和分类,可以准确地分析出不同的烟雾、火焰等特征,并及时发出警报或提醒相关管理人员。这种高效的监测和识别能力可以帮助监测中心快速反应异常情况…

ServletContext 的 4 个常见应用!

一、ServletContext类详解 Web容器在启动时,会为每一个Web项目创建一个对应的ServletContext对象。它是当前项目中所有Servlet实例之间信息交互的“中间商”。(参见“Servlet的运行原理”) 注:一个Web项目对应一个ServletContext。(即:同一个Web项目中的所有servlet实例共…

Servlet 映射(访问)路径的 3 种方式!

Servlet的映射(访问)路径是在Web配置文件(web.xml)中编写的。如: <!-- Servlet的访问路径 --> <servlet-mapping><servlet-name>servlet1</servlet-name><url-pattern>/hello</url-pattern> </servlet-mapping>1、servlet映射…

Java初学者笔记-05、集合框架

集合体系 集合是可变长的。 Collection:代表单列集合,每个元素包含一个值。 Map:代表双列集合,每个元素包含两个值。 Collection集合List系列集合:添加的元素是有序、可重复、有索引。ArrayList、 LinekdList:有序、可重复、有索引。Set系列集合:添加的元素是无序、不重…

.NET周刊【1月第1期 2025-01-05】

国内文章 3款.NET开源、功能强大的通讯调试工具,效率提升利器! https://www.cnblogs.com/Can-daydayup/p/18631410 本文介绍了三款功能强大的.NET开源通讯调试工具,旨在提高调试效率。这些工具包括LLCOM,提供串口调试和自动化处理功能;Wu.CommTool,支持Modbus RTU和MQTT调…

Servlet 详解!

一、Servlet简介 Servlet是Sun公司开发动态Web的一门技术。Sun公司在这些API中提供了一个Servlet接口,如果你想开发一个Servlet程序只需要完成如下两个步骤: 1、编写一个Java类实现Servlet接口。 2、把开发好的Java类部署到Web服务器中。 我们把实现了Servlet接口的Java程序叫…