bzoj2120: 数颜色

妈也第三次补莫队。。。

好吧大概是以后不用补了。

讲一讲,首先操作就是离线,把询问和修改记录下来,特别要注意的,询问要记录该询问前有多少个修改ti,修改要记录修改前的颜色pre。

第二步就是分块,然后按l,r,ti块的顺序排序

然后这个暴力怎么写呢。

主要的思想就是将当前的延伸到要求的。带修就是三维l,r,T了。

假设当前求出了一个询问,那么l,r,T,都等于这个询问的值,按顺序要求新询问

那么按照T,l,r的顺序,暴力恢复到满足三个条件就可以了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int n,m,a[11000];

struct query
{
    int l,r,ti,id;
}q[11000];int qlen;
struct change_color
{
    int ip,now,pre;//pre记录这个修改前的颜色 
}c[11000];int clen,last[11000];//last是最后的颜色 

int block,st[11000];
bool cmp(query n1,query n2)
{
    if((st[n1.l]<st[n2.l]) ||
        (st[n1.l]==st[n2.l]&&st[n1.r]<st[n2.r]) ||
            (st[n1.l]==st[n2.l]&&st[n1.r]==st[n2.r]&&st[n1.ti]<st[n2.ti]))
                return true;
    return false;
}

int as[11000];
int col[1100000],ans;
void change(int x,int k)
{
    col[x]+=k;
    if(k==-1&&col[x]==0)ans--;
    if(k==1&&col[x]==1)ans++;
}
void solve()
{
    int l=1,r=0,T=0;
    for(int i=1;i<=qlen;i++)
    {
        while(T<q[i].ti)
        {
            T++;
            if(l<=c[T].ip&&c[T].ip<=r)//释放对答案的影响 
                change(a[c[T].ip],-1), change(c[T].now,1);
            a[c[T].ip]=c[T].now;//位置的颜色更改
        }//时间加速
        while(T>q[i].ti)
        {
            if(l<=c[T].ip&&c[T].ip<=r)
                change(a[c[T].ip],-1), change(c[T].pre,1);
            a[c[T].ip]=c[T].pre;
            T--;
        }//时间倒流
        
        //ti
        
        while(l<q[i].l)change(a[l],-1), l++;
        while(l>q[i].l)l--, change(a[l],1);
        while(r<q[i].r)r++, change(a[r],1);
        while(r>q[i].r)change(a[r],-1), r--;
        //l&r
        
        as[q[i].id]=ans;
    }
}

char ss[20];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]), last[i]=a[i];
        
    int x,y;
    for(int i=1;i<=m;i++)
    {
        scanf("%s%d%d",ss+1,&x,&y);
        if(ss[1]=='Q')
        {
            qlen++;
            q[qlen].l=x;q[qlen].r=y;
            q[qlen].ti=clen;q[qlen].id=qlen;
        }//qins
        else if(ss[1]=='R')
        {
            clen++;
            c[clen].ip=x;c[clen].now=y;
            c[clen].pre=last[x];last[x]=y;
        }//cins
    }
    
    //离线 
    
    block=int(pow(n,0.66666));
    for(int i=1;i<=n;i++)st[i]=(i-1)/block+1;
    sort(q+1,q+qlen+1,cmp);
    
    ans=0;
    solve();
    
    for(int i=1;i<=qlen;i++)printf("%d
",as[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/AKCqhzdy/p/7772883.html