• BZOJ 2120 数颜色(带修改的莫队)


    2120: 数颜色

    Time Limit: 6 Sec  Memory Limit: 259 MB
    Submit: 3478  Solved: 1342
    [Submit][Status][Discuss]

    Description

    墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?

    Input

    第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

    Output

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

    Sample Input

    6 5
    1 2 3 4 5 5
    Q 1 4
    Q 2 6
    R 1 2
    Q 1 4
    Q 2 6

    Sample Output

    4
    4
    3
    4

    HINT

     

    对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。


    2016.3.2新加数据两组by Nano_Ape

    题目链接:BZOJ 2120

    一直比较喜欢莫队的暴力式算法,但是会的都too simple,这题的莫队里加了一个修改的操作就比纯暴力有意思,但是这样加上去要如何修改呢?修改的顺序应该是怎么样的呢?

    一种解法是将询问和修改操作分开存放,询问要增加一个记录当前询问时已出现修改次数的变量t,再继续按照原来莫队的排序顺序进行排序,修改则是用另外的结构体存放修改位置和修改之前这个位置的值(至于为什么要存之前的值后面会说),每一次先把区间移动好,再看操作次数T与当前询问的t之间的关系,若不同则要进行撤回或者更新,怎么撤回更新呢?这时候就要用到修改结构体中记录修改前的值的作用了,每一次撤回或者更新,都把当前的val与当前修改的位置的值作交换,那么假设是更新,把原来的值交换到了现在的val里,现在的arr[x]中是修改后的val,假设又要撤回了,那又一次地把val与arr[x]交换,这样确实做到了撤回,为什么可以这样呢?因为在更新的时候T的变化是连续的而不是跳跃着更新,不然这个修改结构体里的val多经过几次修改就会对不上号了。

    其中需要注意一些细节,比如说询问的存放显然是可以从0~cnt_query,但是询问的t肯定是从1开始的,因此记录修改次数的cc要先自增1再把修改操作存入C[cc]……然后就是++ -- 对应的判断1或0别写反了就行……写完发现比原来参考的别人的题解速度快一倍,真是奇怪……,哦还有另外一种做法就是主席树+树状数组,然而并不会就只能默默地学习一个莫队了

    送一组发现了某处低级错误错误的数据

    2 4
    1 2
    Q 1 2
    R 1 3
    Q 1 2
    Q 1 1

    Ans
    2
    2
    1

    代码:

    #include <stdio.h>
    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define CLR(arr,val) memset(arr,val,sizeof(arr))
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    typedef pair<int,int> pii;
    typedef long long LL;
    const double PI=acos(-1.0);
    const int N=10010;
    const int M=1000007;
    struct info
    {
        int l,r,t;
        int b,id;
        bool operator<(const info &t)const
        {
            if(b==t.b)
                return r<t.r;
            return b<t.b;
        }
    };
    struct modify
    {
        int pos;
        int val;
    };
    
    modify C[N];
    info Q[N];
    int arr[N],ans[N],vis[M];
    char ops[3];
    
    int main(void)
    {
        int n,m,l,r,x,i,val;
        while (~scanf("%d%d",&n,&m))
        {
            CLR(vis,0);
            CLR(ans,0);
            int unit=(int)sqrt(n);
    
            for (i=1; i<=n; ++i)
                scanf("%d",&arr[i]);
    
            int cq=0,cc=0;
            for (i=0; i<m; ++i)
            {
                scanf("%s",ops);
                if(ops[0]=='Q')
                {
                    scanf("%d%d",&l,&r);
                    Q[cq].l=l;
                    Q[cq].r=r;
                    Q[cq].b=Q[cq].l/unit;
                    Q[cq].id=cq;
                    Q[cq].t=cc;
                    ++cq;
                }
                else
                {
                    ++cc;
                    scanf("%d%d",&x,&val);
                    C[cc].pos=x;
                    C[cc].val=val;
                }
            }
            sort(Q,Q+cq);
            int L=1,R=0,T=0;
            int temp=0;
    
            for (i=0; i<cq; ++i)
            {
                while (L<Q[i].l)
                {
                    if(--vis[arr[L]]==0)
                        --temp;
                    ++L;
                }
                while (L>Q[i].l)
                {
                    --L;
                    if(++vis[arr[L]]==1)
                        ++temp;
                }
                while (R<Q[i].r)
                {
                    ++R;
                    if(++vis[arr[R]]==1)
                        ++temp;
                }
                while (R>Q[i].r)
                {
                    if(--vis[arr[R]]==0)
                        --temp;
                    --R;
                }
                while (T<Q[i].t)///大于区间
                {
                    ++T;
                    if(L<=C[T].pos&&C[T].pos<=R)
                    {
                        if(--vis[arr[C[T].pos]]==0)
                            --temp;
                    }
                    swap(C[T].val,arr[C[T].pos]);
                    if(L<=C[T].pos&&C[T].pos<=R)
                    {
                        if(++vis[arr[C[T].pos]]==1)
                            ++temp;
                    }
                }
                while (T>Q[i].t)///缩小区间
                {
                    if(L<=C[T].pos&&C[T].pos<=R)
                    {
                        if(--vis[arr[C[T].pos]]==0)
                            --temp;
                    }
                    swap(C[T].val,arr[C[T].pos]);
                    if(L<=C[T].pos&&C[T].pos<=R)
                    {
                        if(++vis[arr[C[T].pos]]==1)
                            ++temp;
                    }
                    --T;
                }
                ans[Q[i].id]=temp;
            }
            for (i=0; i<cq; ++i)
                printf("%d
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    ThinkPHP5如何引用新建的配置文件?
    MySQL与SQLServer的update left join语法区别
    如何POST一个JSON格式的数据给java接口,获得返回数据
    如何使用ThinkPHP5 ,自动生成目录?
    LeetCode347_TopK
    数据结构算法Review1_堆
    OJ_3_字符串数字相互转换
    C++Review11_指针数组和数组指针
    LeetCode15_三数之和
    LeetCode1_两数之和
  • 原文地址:https://www.cnblogs.com/Blackops/p/5984926.html
Copyright © 2020-2023  润新知