P1903 [国家集训队]数颜色 / 维护队列

传送门

带修莫队,在原来的基础上加一个时间指针 $t$

每次移动时除了 $l,r$ 移动 $t$ 也跟着移动,并更新状态

为了维护时间变化

所以维护一个 $pos[i]$ 表示第 $i$ 次修改的位置,$co[i]$ 表示第 $i$ 次修改的颜色

$pre[i]$ 表示第 $i$ 次修改前 $pos[i]$ 的颜色

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=1e5+7,M=1e6+7;
int n,m,Div;
int cnt[M],col[N],ans[N];//col维护当前序列状态
int pos[N],pre[N],co[N];
struct dat{
    int l,r,t,bel;
    inline bool operator < (const dat &tmp) const {
        if(l/Div!=tmp.l/Div) return l/Div<tmp.l/Div;
        return r/Div!=tmp.r/Div ? r/Div<tmp.r/Div : t/Div<tmp.t/Div;
    }
}q[N];
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++) col[i]=read();
    int ta=0,tb=0,a,b; char s[7];
    for(int i=1;i<=m;i++)
    {
        scanf("%s",s); a=read(),b=read();
        if(s[0]=='Q')
            q[++ta]=(dat){a,b,tb,ta};
        else
        {
            tb++; pos[tb]=a; co[tb]=b;
            pre[tb]=col[a]; col[a]=b;
        }
    }
    for(int i=tb;i;i--) col[pos[i]]=pre[i];//把序列的修改撤销回来
    Div=ceil( exp( (log(n)+log(tb))/3 ) );//奇怪的块大小
    sort(q+1,q+ta+1);
    int l=1,r=0,t=0,tot=0;
    for(int i=1;i<=ta;i++)
    {
        while(q[i].l<l) tot+=!cnt[col[--l]]++;
        while(q[i].l>l) tot-=!--cnt[col[l++]];
        while(q[i].r<r) tot-=!--cnt[col[r--]];
        while(q[i].r>r) tot+=!cnt[col[++r]]++;
        while(q[i].t<t)//移动时间指针
        {
            if(pos[t]>=l&&pos[t]<=r) tot-=!--cnt[col[ pos[t] ]];
            col[pos[t]]=pre[t];
            if(pos[t]>=l&&pos[t]<=r) tot+=!cnt[col[ pos[t] ]]++;
            t--;
        }
        while(q[i].t>t)//移动时间指针
        {
            t++;
            if(pos[t]>=l&&pos[t]<=r) tot-=!--cnt[col[ pos[t] ]];
            col[pos[t]]=co[t];
            if(pos[t]>=l&&pos[t]<=r) tot+=!cnt[col[ pos[t] ]]++;
        }
        ans[q[i].bel]=tot;
    }
    for(int i=1;i<=ta;i++) printf("%d\n",ans[i]);
    return 0;
}

 

猜你喜欢

转载自www.cnblogs.com/LLTYYC/p/10630996.html
今日推荐