语文1(chin1)- 理理思维题解

· · 题解

操作二将第xi到第yi个字符全部替换为ki

你想到了什么?

没错,推平一段区间,珂朵莉树基本操作。

珂朵莉树,优雅的暴力。

珂朵莉树模板题 题解中有对珂朵莉树的详细解释

珂朵莉就是把每个数字分为三元组l,r,v,表示a[l]~a[r]都是v

一般是用set实现,但我是用链表实现的。

之后就类似暴力的实现了

#include<bits/stdc++.h>
using namespace std;

#define MAXN 100005
char s[MAXN];
int n,m,nn;
struct aa
{
    int l,r,rr;
    char v;
}a[MAXN*30];
int c[50];

void wt()//调试用
{
    cout<<"-----------------\n";
    for(int i = n+1; i != 0; i = a[i].rr)
    {
        cout<<a[i].l<<" "<<a[i].r<<" "<<a[i].v<<"\n";
    }
    cout<<"-----------------\n";
}

void he()//合并
{
    for(int i = n+1; i != 0; i = a[i].rr)
    {
        while(a[i].v == a[a[i].rr].v && a[i].rr != 0)
        {
            a[i].r = a[a[i].rr].r;
            a[i].rr = a[a[i].rr].rr;
        }
    }
}

void rd()
{
    scanf("%d%d",&n,&m);
    scanf("%s",s+1);
    for(int i = 1; i <= n; i ++)
    {
        if(s[i] <= 'Z' && s[i] >= 'A')
            s[i] = s[i] -'A' + 'a';
        a[i].l = i;
        a[i].r = i;
        a[i].v = s[i];
        if(i != n)
            a[i].rr = i+1;
    }
    a[n+1].rr = 1;
    a[n].rr = n+2;
    nn = n+2;
    he();
}

void fen(int i,int x)
{
    nn ++;
    a[nn].rr = a[i].rr;
    a[nn].r = a[i].r;
    a[nn].l = x;
    a[nn].v = a[i].v; 
    a[i].rr = nn;
    a[i].r = x-1;
} 

int paix(int l,int r,int p,char ch)//p代表操作
{
    memset(c,0,sizeof(c));
    for(int i = n+1; i != 0; i = a[i].rr)//先在将部分在处理区间内部分区间外的分离,方便之后操作
    {
        if(a[i].l < l && a[i].r >= l) fen(i,l); 
        if(a[i].l <= r && a[i].r > r) fen(i,r+1);
    }
    bool t = 0;
    int lp,rp;

    for(int i = n+1; i != 0; i = a[i].rr)
    {
        if(a[i].l >= l && a[i].r <= r)
        {
            if(p == 2)
                a[i].v = ch; 
            c[a[i].v-'a'] += a[i].r - a[i].l + 1;//统计每种字母出现次数
            t = 1;
        }
        else
        {
            if(t)
            {
                rp = i;
                break;
            }
            else lp = i;
        }
    }
    if(p == 2)
    {
        he();
        return 0;
    }
    if(p == 1)
    {
        he(); 
        return c[ch-'a'];
    }
    int u = a[lp].r,x = lp;
    for(int i = 0; i <= 26; i ++)//排序时重新插入
    if(c[i] != 0)
    {
        nn ++;
        a[x].rr = nn;
        x = nn;
        a[nn].v = 'a' + i;
        a[nn].l = u+1;
        a[nn].r = u + c[i];
        u += c[i];
    }

    a[x].rr = rp;
    he();
    return 0;
} 


int main()
{

    rd();
    for(int i = 1; i <= m; i ++)
    {
        int l,r,opt;
        string s;
        scanf("%d",&opt);
        if(opt == 1)
        {
            cin >> l >> r >> s;
            if(s[0] < 'a')
                s[0] = s[0]  - 'A'+ 'a';
            cout<<paix(l,r,1,s[0])<<"\n";

        }
        if(opt == 2)
        {
            cin >> l >> r >> s;
            if(s[0] < 'a')
                s[0] = s[0] - 'A' +  'a';
            paix(l,r,2,s[0]);
        }
        if(opt == 3)
        {
            cin >> l >> r;
            paix(l,r,0,'a');
        }
    }
    return 0;
}