bzoj2120 数颜色——带修莫队

Posted zinn

tags:

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

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2120

带修改的莫队;

用结构体存下修改和询问,排好序保证时间后就全局移动修改即可;

参考了TJ:https://blog.csdn.net/SmallSXJ/article/details/69676746

vis 标记得好精妙啊!这样修改都不用分别改加入和删除了!

还要注意区间的扩展和收缩在循环上有微妙不同,一定不要写错;

所以带修莫队也很简洁嘛!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int const maxn=1e4+5;
int n,m,a[maxn],b[maxn],pos[maxn],res,ans[maxn],base,cnt,tot,num[maxn*100];
bool vis[maxn];
struct N{int bh,x,y;}ch[maxn];
struct T{int pre,l,r,id;}q[maxn];
bool cmp(T x,T y){return (pos[x.l]==pos[y.l])?x.r<y.r:pos[x.l]<pos[y.l];}
void change(int p)
{
    if(vis[p])
    {
        num[a[p]]--;
        if(num[a[p]]==0)res--;
    }
    else
    {
        num[a[p]]++;
        if(num[a[p]]==1)res++;
    }
    vis[p]^=1;
}
void update(int p,int x)//a[p]=x
{
    if(vis[p])
    {
        change(p);
        a[p]=x;
        change(p);
    }
    else a[p]=x;
}
void work()
{
    int nw=0,l=1,r=0;//
    for(int i=1;i<=m;i++)
    {
//        while(nw<=q[i].pre)update(ch[nw].bh,ch[nw].y),nw++;
//        while(nw>q[i].pre)update(ch[nw].bh,ch[nw].x),nw--;
//        while(l<q[i].l)change(l),l++;
//        while(l>q[i].l)change(l),l--;
//        while(r<q[i].r)change(r),r++;
//        while(r>q[i].r)change(r),r--;
//        ans[q[i].id]=res;
        for(int j=nw+1;j<=q[i].pre;j++)
            update(ch[j].bh,ch[j].y);
        for(int j=nw;j>q[i].pre;j--)
            update(ch[j].bh,ch[j].x);
        for(int j=r+1;j<=q[i].r;j++) change(j);//注意扩展和收缩的不同! 
        for(int j=r;j>q[i].r;j--) change(j);
        for(int j=l-1;j>=q[i].l;j--) change(j);
        for(int j=l;j<q[i].l;j++) change(j);
        ans[q[i].id]=res;
        l=q[i].l,r=q[i].r,nw=q[i].pre;
    }
}
int main()
{
    scanf("%d%d",&n,&m); base=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        pos[i]=(i-1)/base+1;
        scanf("%d",&a[i]); b[i]=a[i];
    }
    char cc[3];
    for(int i=1,x,y;i<=m;i++)
    {
        cin>>cc;
        scanf("%d%d",&x,&y);
        if(cc[0]==R)
        {
            ch[++tot].bh=x; ch[tot].x=b[x]; ch[tot].y=y;
            b[x]=y;
        }
        else q[++cnt].pre=tot,q[cnt].l=x,q[cnt].r=y,q[cnt].id=cnt;
    }
    sort(q+1,q+m+1,cmp);
    work();
    for(int i=1;i<=cnt;i++)printf("%d
",ans[i]);
    return 0;
}

 

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

[带修莫队] Bzoj 2120 数颜色

bzoj2120: 数颜色

2120: 数颜色(带修莫队)

bzoj 2120: 数颜色带修改莫队

Luogu1903数颜色(带修莫队)

数颜色 / 维护队列(带修莫队板子)