洛谷 2787 珂朵莉树(ODT)

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

P 2787 P2787 P2787
参考代码:

/*
 * @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 ll long long
//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 it set<node>::iterator
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);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/yangzijiangac/article/details/108755554