• 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;
    }
  • 相关阅读:
    团队作业2:需求分析&原型设计
    第0次作业
    asp.net创建文件夹出错的解决方案[转]
    C# 线程手册 第一章 线程定义 线程
    Apache+php+mysql在windows下的安装与配置图解
    对于访问IIS元数据库失败的解决
    通过设置CSS position 属性来固定层的位置
    vs2008快捷键极其技巧 转载
    大文件上传组件
    C#代码备份还原MSSQL数据库
  • 原文地址:https://www.cnblogs.com/Zinn/p/9332556.html
Copyright © 2020-2023  润新知