[补题]百度之星2024省赛第三场

BD202418 激光控制器在这里插入图片描述

思路:
map差分+离散化

代码:

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
map<int,int> m;
int a[200005][2];

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int N;
	int ans = 0,now =0;
	cin >> N;
	for (int i = 0; i < N; i++) {
		int x;
		char op;
		cin >> x >> op;
		if(op=='L'){  //在差分数组头尾加减1,实现区间加1
			m[now+1]--;
			m[now-x+1]++;
			now-=x-1;
		}
		else{
			m[now]++;
			m[now+x]--;
			now+=x-1;
		}
	}
	int index=0;
	for(pair<int,int> e: m){  //进行离散化,将每段记录成数组,第一行为位置,第二行为长度
		a[index][1]=e.second;
		a[index++][0]=e.first;
//		cout<<a[index-1][0]<<" "<<a[index-1][1]<<endl;
	}
	for(int i=1;i<index;i++){
		a[i][1]+=a[i-1][1];  //前缀和即为该段修改次数,模4找到向东的段累加答案
		if(a[i-1][1]%4 == 1 )
			ans += a[i][0]-a[i-1][0];
	}
	cout<<ans;
	return 0;
}

BD202419 好像相等

在这里插入图片描述

思路:
字符串哈希
直接暴力明显会超时。这里考虑到,在两个字符串s1,s2上,对于某个字符x出现的位置分布,只要有一个地方不相同,那么x就应当被*替代,即出现在答案中。而小写字母一共只有26种,只需要单独保存不同种类字符位置的哈希值,看子区间中位置哈希值是否相同。
O(1)求字串的哈希值的方法:
若已知一个 S = s 1 s 2 . . . s n S = s_1s_2...s_n S=s1s2...sn的字符串的 h a s h hash hash值, h a s h [ i ] , 0 ≤ i ≤ n hash[i],0≤i≤n hash[i],0in,其子串 s l . . . s r s_l...s_r sl...sr,对应的hash值为:
r e s = h a s h [ r ] − h a s h [ l − 1 ] ∗ B a s e r − l + 1 res = hash[r] - hash[l-1] * Base^{r - l + 1} res=hash[r]hash[l1]Baserl+1

代码:

#include <bits/stdc++.h>
#define endl '\n'
typedef long long ll;
using namespace std;
const int N = 1e5 + 5, base = 233;
ll p[N] = {1}, hs[N][26];

int main() {
	cin.tie(0)->ios::sync_with_stdio(0);
	string s;
	int n, q;
	cin >> n >> q >> s;
	for (int i = 1; i <= n; i++) { //预处理得到每种字符的位置哈希值
		for (int j = 0; j < 26; j++) {
			//这里只计算特定字符的哈希值,其他字符无贡献(视为一致)
			hs[i][j] = hs[i - 1][j] * base + s[i - 1] * (s[i - 1] == 'a' + j);
			p[i] = p[i - 1] * base;
		}
	}
	while (q--) {
		int l1, r1, l2, r2;
		cin >> l1 >> r1 >> l2 >> r2;
		int len = r1 - l1 + 1;
		vector<char> ans;
		for (int i = 0; i < 26; i++) {
			//比较两个字串的哈希值。如果不等,则该字符对答案有贡献。
			if (hs[r1][i] - hs[l1 - 1][i]*p[len] != hs[r2][i] - hs[l2 - 1][i]*p[len]) {
				ans.push_back('a' + i);
			}
		}
		cout << ans.size() << endl;
		for (char ch : ans)cout << ch;
		cout << endl;
	}

	return 0;
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值