带修莫队板子

https://www.luogu.org/problem/P1903

#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
struct Query{ //查询
    int l,r,t,id;
}q[51000];
struct Modify{// 回退
    int p,col; //p代表修改的下标
}mo[51000];
int n,m,cnt1,cnt2,len,s,l = 1,r,t;
int a[51000],c[1001000],ans[51000],tti[51000];
//tti是修改的次数,c代表颜色种类,ans存的答案,a存的原数组
char opt;
bool cmp(Query x,Query y){
    if (x.l/len!=y.l/len) return x.l/len<y.l/len;
    if (x.r/len!=y.r/len) return x.r/len<y.r/len;
    return x.t<y.t; //按照时间排序
}
void add(int x){
    c[x]++;
    if(c[x]==1) s+=c[x];
}
void del(int x){
    c[x]--;
    if(c[x]==0) s--;
}
void replace(int x){  //交换时间轴
    int xx=mo[tti[t]].p;  //xx为第tti[t]次的修改的位置
    if (xx>=l&&xx<=r){  
        s-=!(--c[a[mo[tti[t]].p]]);  //
        s+=!(c[mo[tti[t]].col]++);
    }
    swap(a[mo[tti[t]].p],mo[tti[t]].col);
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for (int i=1;i<=n;i++) cin>>a[i];
    for (int i=1;i<=m;i++){
        cin>>opt;
        if (opt=='Q'){
            ++cnt1;
            cin>>q[cnt1].l>>q[cnt1].r;
            q[cnt1].t=i;
            q[cnt1].id=cnt1;
        }
        else{
            ++cnt2;
            cin>>mo[cnt2].p>>mo[cnt2].col;
            tti[i]=cnt2; //存的修改的编号
        }
    }
    len=pow(n,2.0/3);  //分块
    sort(q+1,q+cnt1+1,cmp);
    for (int i=1;i<=cnt1;++i){
        while (t<q[i].t) if(tti[++t]) replace(t);
        while (t>q[i].t) if(tti[--t]) replace(t);
        while (l>q[i].l) add(a[--l]);
        while (l<q[i].l) del(a[l++]);
        while (r>q[i].r) del(a[r--]);
        while (r<q[i].r) add(a[++r]);
        ans[q[i].id]=s;
    }
    for (int i=1;i<=cnt1;i++) cout<<ans[i]<<endl;
}

猜你喜欢

转载自www.cnblogs.com/wushengyang/p/11268288.html