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],0≤i≤n,其子串
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[l−1]∗Baser−l+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;
}