• 洛谷 P1903 [国家集训队]数颜色 解题报告


    P1903 [国家集训队]数颜色

    题目描述

    墨墨购买了一套(N)支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:

    1、Q L R代表询问你从第(L)支画笔到第(R)支画笔中共有几种不同颜色的画笔。

    2、 R P Col 把第(P)支画笔替换为颜色(Col)

    为了满足墨墨的要求,你知道你需要干什么了吗?

    输入输出格式

    输入格式:

    第1行两个整数(N)(M),分别代表初始画笔的数量以及墨墨会做的事情的个数。

    第2行(N)个整数,分别代表初始画笔排中第i支画笔的颜色。

    第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

    输出格式:

    对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。

    说明

    对于100%的数据,N≤50000,M≤50000,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。


    正解是待修莫队,不过树套树复杂度更优秀(常数就不一定了),就拿树套树过了这个题

    把一个颜色的笔放到一个set里,以位置为关键字,同时更新(pre)数组,代表前一个相同颜色的位置(特别的,如果没有,为0)

    先不考虑修改,我们发现询问([l,r])有多少不同颜色等价于询问有多少个(pre)数组小于(l),我们可以拿权值线段树解决这个问题

    然后对于修改,我们只需要在外面套上树状数组就可以啦


    Code:

    #include <cstdio>
    #include <algorithm>
    #include <set>
    #define ls ch[now][0]
    #define rs ch[now][1]
    using namespace std;
    const int N=2e5+10;
    int ch[N*18][2],sum[N*18],root[N],tot;
    int a[N],b[N],pre[N],n,m,k;
    void updata(int now){sum[now]=sum[ls]+sum[rs];}
    void change(int &now,int l,int r,int pos,int delta)
    {
        if(!now) now=++tot;
        if(l==r) {sum[now]+=delta;return;}
        int mid=l+r>>1;
        if(pos<=mid) change(ls,l,mid,pos,delta);
        else change(rs,mid+1,r,pos,delta);
        updata(now);
    }
    int query(int now,int l,int r,int pos)
    {
        if(!now||l==r) return 0;
        int mid=l+r>>1;
        if(pos<=mid) return query(ls,l,mid,pos);
        else return sum[ls]+query(rs,mid+1,r,pos);
    }
    void modify(int x,int pos,int delta)
    {
        while(x<=n) change(root[x],0,n-1,pos,delta),x+=x&-x;
    }
    int ask(int x,int rk)
    {
        int ans=0;
        while(x)
            ans+=query(root[x],0,n-1,rk),x-=x&-x;
        return ans;
    }
    struct node{int op,x,y;}opt[N];
    set <int > rb[N];
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
        m=n;char c[3];
        for(int i=1;i<=k;i++)
        {
            scanf("%s%d%d",c,&opt[i].x,&opt[i].y);
            opt[i].op=(c[0]=='R');
            if(opt[i].op) a[++m]=opt[i].y;
        }
        sort(a+1,a+1+m);
        m=unique(a+1,a+1+m)-a-1;
        for(int i=1;i<=n;i++) b[i]=lower_bound(a+1,a+1+m,b[i])-a;
        for(int i=1;i<=k;i++) if(opt[i].op) opt[i].y=lower_bound(a+1,a+1+m,opt[i].y)-a;
        for(int i=1;i<=n;i++)
        {
            if(!rb[b[i]].empty())
            {
                set <int>::iterator it=rb[b[i]].end();
                it--;
                pre[i]=*it;
            }
            rb[b[i]].insert(i);
        }
        for(int i=1;i<=n;i++)
            for(int j=i-(i&-i)+1;j<=i;j++)
                change(root[i],0,n-1,pre[j],1);
        for(int i=1;i<=k;i++)
        {
            if(opt[i].op)
            {
                int co=opt[i].y,pos=opt[i].x,pr;
                set <int >::iterator it=rb[b[pos]].find(pos);//找到颜色位置
                it++;
                if(it!=rb[b[pos]].end())//改它的后继
                {
                    modify(*it,pos,-1);
                    modify(*it,pre[*it]=pre[pos],1);
                }
                rb[b[pos]].erase(pos);//删掉
                rb[b[pos]=co].insert(pos);//加入且改自己颜色
                it=rb[co].find(pos);
                if(it!=rb[co].begin()) it--,pr=*it,it++;
                else pr=0;//找到pre
                modify(pos,pre[pos],-1);//改自己pre
                modify(pos,pre[pos]=pr,1);
                it++;
                if(it!=rb[b[pos]].end())//寻找后面
                {
                    modify(*it,pre[*it],-1);
                    modify(*it,pre[*it]=pos,1);
                }
            }
            else
                printf("%d
    ",ask(opt[i].y,opt[i].x)-opt[i].x+1);
        }
        return 0;
    }
    
    

    2018.9.4

  • 相关阅读:
    vue.nextTick()方法简单理解
    vue中 hash和history的区别
    Set,Map一些常见的遍历方法以及转化方法
    vue中import和require的用法
    $route和 $router的区别是什么
    vue vmodel的总结
    vue router的钩子函数总结
    了解promise和async await的区别
    ZOJ 1642 Match for Bonus
    UVA 10003 Cutting Sticks
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9588311.html
Copyright © 2020-2023  润新知