数据被加强了,洛谷 2787 珂朵莉树(ODT)_i++无法水过这个题了,但我还是要写一写这个新学习的黑科技算法。
这个算法,和洛谷 2787 珂朵莉树(ODT)_#include_02一样很香,但唯一不同点是,洛谷 2787 珂朵莉树(ODT)_#include_02众所周知,而珂朵莉树洛谷 2787 珂朵莉树(ODT)_i++鲜为人知,他们过随机数据都十分快。
洛谷 2787 珂朵莉树(ODT)_i++是基于洛谷 2787 珂朵莉树(ODT)_#include_06里面的洛谷 2787 珂朵莉树(ODT)_#define_07来实现的,通过一个平推操作,使复杂度快速下降,平推操作可以使洛谷 2787 珂朵莉树(ODT)_#define_07容器中的数量快速下降,从而做到近似洛谷 2787 珂朵莉树(ODT)_#define_09的时间复杂度,在空间上更是吊锤线段树。

洛谷 2787 珂朵莉树(ODT)_i++_10
参考代码:

/*
* @Author: vain
* @Date: 2020
* @LastEditTime: 2020-09-23 16:07:46
* @LastEditors: sueRimn
* @Description: 学不会 dp 的 fw
* @FilePath: \main\demo.cpp
*/
//#include <bits/stdc++.h>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
#include <bitset>
using namespace std;
typedef long long ll;
#define
//typedef unsigned long long uint;
const int N = 1e3 + 20;
const int maxn = 1e5 + 20;
// typedef pair<int, int> p;
// priority_queue<p, vector<p>, greater<p>> m;
//int sum[maxn];
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
int lcm(int a, int b) { return a * b / gcd(a, b); }
void swap(int &x, int &y) { x ^= y, y ^= x, x ^= y; }
int lowbit(int x) { return (x) & (-x); }
int rechar[35];
struct node
{
mutable int l, r;
mutable char v;
node(int L = 0, int R = -1, char v = 'a') : l(L), r(R), v(v){};
bool operator<(const node &x) const
{
return l < x.l;
}
};
#define
set<node> S;
it split(int pos)
{
it p = S.lower_bound(node(pos));
if (S.end() != p && p->l == pos)
return p;
--p;
int l = p->l, r = p->r;
char v = p->v;
S.erase(p);
S.insert(node(l, pos - 1, v));
return S.insert(node(pos, r, v)).first;
}
void push(int l, int r, char c)
{
it itr = split(r + 1), itl = split(l);
S.erase(itl, itr);
S.insert(node(l, r, c));
}
void Sort(int l, int r)
{
for (int i = 0; i < 30; i++)
rechar[i] = 0;
it itr = split(r + 1), itl = split(l);
it itx = itl;
for (; itl != itr; itl++)
{
rechar[itl->v - 'A'] += itl->r - itl->l + 1;
}
S.erase(itx, itr);
for (int i = 0; i < 26; i++)
{
if (rechar[i])
{
S.insert(node(l, l + rechar[i] - 1, i + 'A'));
l += rechar[i];
}
}
}
char C(char c)
{
if (c >= 'A' && c <= 'Z')
return c;
return c - 32;
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0), cout.tie(0);
int n, q;
//cout << char(toupper('a')) << endl;
cin >> n >> q;
string s;
cin >> s;
for (int i = 0; i < n; i++)
S.insert(node(i + 1, i + 1, C(s[i])));
for (int i = 1; i <= q; i++)
{
int l, r, k;
scanf("%d %d %d", &k, &l, &r);
getchar();
if (k == 1)
{
char c;
int ans = 0;
scanf("%c", &c);
it itr = split(r + 1), itl = split(l);
for (; itl != itr; itl++)
{
if (itl->v == C(c))
ans += itl->r - itl->l + 1;
}
printf("%d\n", ans);
}
if (k == 2)
{
char c;
scanf("%c", &c);
push(l, r, C(c));
}
if (k == 3)
{
Sort(l, r);
}
}
}