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

链接: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+97
		if (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;
}

posted @ 2025-01-19 14:21  WHUStar  阅读(17)  评论(0)    收藏  举报