【洛谷题解】AT_abc415_f 题解

怎么说呢。它的这个思路并不是很难,然后吧,个人感觉这个代码的细节并不是很多。

我是比赛一结束就会了,然后立刻补的。没怎么调,一下子就过了。

就是说,这东西是个很显然的线段树。它处理的是单点修改区间查询。

那线段树要维护啥呢?其实也很显然。或者说,比较典。

首先是这个区间的这个 \(\max\) 的长度,对吧,就记作 \(mx\) 好了。

然后呢,区间合并,也就是 push_up 的时候,还需要用到每个区间左边一段同样字母的情况,以及右边一段同样字母的情况。

左边一段字母是 \(Lh\),长度为 \(Lc\),右边的话字母 \(Rh\) 长度 \(Rc\)

那就没事了,去维护就成。

这还是没啥难度的吧。

代码……不算很长,然后感觉细节也不多,大家看着来吧。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 2e6+5;
struct Tree{
    int Lc;char Lh;
    int Rc;char Rh;
    int mx,len;
}t[N];
int n,Q;
string s;
int ls(int u){return (u<<1);}
int rs(int u){return (u<<1|1);}
Tree operator + (const Tree x,const Tree y){
    Tree A;
    A.mx=max(x.mx,y.mx);
    A.len=x.len+y.len;
    if(x.Rh==y.Lh)A.mx=max(A.mx,x.Rc+y.Lc);
    A.Lc=x.Lc,A.Lh=x.Lh;
    if(x.len==x.Lc&&y.Lh==x.Lh)A.Lc+=y.Lc;
    A.Rc=y.Rc,A.Rh=y.Rh;
    if(y.len==y.Rc&&y.Rh==x.Rh)A.Rc+=x.Rc;
    return A;
}
void build(int u,int l,int r){
    if(l==r){t[u]={1,s[l],1,s[r],1,1};return;}
    int mid=(l+r)/2;
    build(ls(u),l,mid);build(rs(u),mid+1,r);
    t[u]=t[ls(u)]+t[rs(u)];return;
}
void change(int u,int l,int r,int LR,char k){
    if(l>LR||r<LR)return;
    if(l==LR&&r==LR){s[l]=k;t[u]={1,k,1,k,1,1};return;}
    int mid=(l+r)/2;
    change(ls(u),l,mid,LR,k);change(rs(u),mid+1,r,LR,k);
    t[u]=t[ls(u)]+t[rs(u)];
    return;
}
Tree query(int u,int l,int r,int L,int R){
    if(L<=l&&r<=R)return t[u];int mid=(l+r)/2;
    if(R<=mid)return query(ls(u),l,mid,L,R);
    if(L>mid)return query(rs(u),mid+1,r,L,R);
    return query(ls(u),l,mid,L,R)+query(rs(u),mid+1,r,L,R);
}
int main(){
    cin>>n>>Q>>s;s=" "+s;build(1,1,n);
    while(Q--){
        int opt;cin>>opt;
        if(opt==1){int i;char x;cin>>i>>x;change(1,1,n,i,x);}
        else{int l,r;cin>>l>>r;cout<<query(1,1,n,l,r).mx<<"\n";}
    }
    return 0;
}
posted @ 2025-07-20 20:21  嘎嘎喵  阅读(37)  评论(0)    收藏  举报