带修莫队板子

Posted wushengyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带修莫队板子相关的知识,希望对你有一定的参考价值。

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;

 

以上是关于带修莫队板子的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2120 数颜色 (带修莫队)

莫队 + 带修莫队

算法笔记莫队算法(基础莫队,带修莫队,回滚莫队,树上莫队,二次离线莫队)

带修莫队

2120: 数颜色(带修莫队)

Machine Learning(带修莫队)