NOIP2023 国庆集训 A 组 Day2
T1
思路:记字母对(l,r),考虑一个字母对(p,q),我们可以统计l在p的左边,r在p,q之间的字母对,也就是左端点l在p左边与该字母对交叉的个数,这样就不会算重。
从左到右扫描字符串,开两个树状数组,第一个以l为下标,第二个以r为下标,一个字母对(p,q)的答案即为第一个树状数组中[1--p - 1]的字母对数量减去第二个树状数组中[1--p - 1]的字母对数量。
AC代码
#include <bits/stdc++.h>
using namespace std;
char s[100001];
int now[26][2],n,tr[2][100001];
long long ans;
bool vis[26];
void update(int x, int y, int op) {
for (;x <= n;x += (x & (-x))) tr[op][x] += y;
}
int query(int x,int op){
int ans = 0;
for(;x;x -= (x & (-x))) ans += tr[op][x];
return ans;
}
int main(){
scanf("%s",s + 1);
n = strlen(s + 1);
for(int i = 1;i <= n;i++){
int id = s[i] - 'a';
if(vis[id]){
now[id][1] = i;
vis[id] = 0;
ans += query(now[id][0] - 1,0) - query(now[id][0] - 1,1);
update(now[id][0],1,0);
update(now[id][1],1,1);
}
else{
vis[id] = 1;
now[id][0] = i;
}
}
cout << ans;
return 0;
}
T2

浙公网安备 33010602011771号