zoukankan      html  css  js  c++  java
  • 2120: 数颜色(带修莫队)

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

    2120: 数颜色

    Time Limit: 6 Sec  Memory Limit: 259 MB
    Submit: 10514  Solved: 4398
    [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

    ·述大意:

           多个区间询问,询问[l,r]中颜色的种类数。可以单点修改颜色。

    ·分析:

    莫队可以修改?那不是爆炸了吗。

    这类爆炸的问题被称为带修莫队(可持久化莫队)。

    按照美妙类比思想,可以引入一个“修改时间”,表示当前询问是发生在前Time个修改操作后的。也就是说,在进行莫队算法时,看看当前的询问和时间指针(第三个指针,别忘了l,r)是否相符,然后进行时光倒流或者时光推移操作来保证答案正确性。

    ·Sort的构造。仅靠原来的sort关键字会使得枚举每个询问都可能因为时间指针移动的缘故要移动n次,总共就n2次,那还不如写暴力。

    ·为了防止这样的事情发生,再加入第三关键字Tim:

    image

    ·如何理解时间复杂度?

    首先,R和Tim的关系就像L和R的关系一样:只有在前者处于同块时,后者才会得到排序的恩赐,否则sort会去满足前者,使得后者开始乱跳。

    依旧像上文那样:枚举m个答案,就一个m了。设分块大小为unit。

    分类讨论:

    ①对于l指针,依旧是O(unit*n)

    ②对于r指针,依旧是O(n*n/unit)

    ③对于T指针(即Time):

        类比r时间复杂度的计算。我们要寻找有多少个单调段(一个单调段下来最多移动n次)。上文提到,当且仅当两个询问l在同块,r也在同块时,才会对可怜的Tim进行排序。局势明朗。对于每一个l的块,里面r最坏情况下占据了所有的块,所以最坏情况下:有n/unit个l的块,每个l的块中会有n/unit个r的块,此时,在一个r块里,就会出现有序的Tim。所以Tim的单调段个数为:(n/unit)*(n/unit)。每个单调段最多移动n次。

    所以:O((n/unit)2*n)

    三个指针汇总:O(unit*n+n2/unit+(n/unit)2*n)

    image

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int maxn=1000000+50;
    int block;
    int a[maxn],b[maxn],ans1[maxn];
    int ans=0;
    struct Q
    {
        int x,y,num,tim;
    }q[maxn];
    struct U
    {
        int x,y;
    }tw[maxn];
    bool cmp(const Q a,const Q b)
    {
        if(a.x/block==b.x/block)
        {
            if(a.y/block==b.y/block) return a.tim<b.tim;
            return a.y/block<b.y/block;
        }
        return a.x/block<b.x/block;
    }
    void solve(int n,int add)
    {
        b[a[n]]+=add;
        if(b[a[n]]==1&&add==1) ans++;
        else if(b[a[n]]==0&&add==-1) ans--;
    }
    void time_charge(int n,int t)
    {
        if(q[n].x<=tw[t].x&&tw[t].x<=q[n].y)
        {
            b[a[tw[t].x]]--;
            if(b[a[tw[t].x]]==0) ans--;
            b[tw[t].y]++;
            if(b[tw[t].y]==1) ans++;
        }
        swap(tw[t].y,a[tw[t].x]);
    }
    int main()
    {
        int N,M,t=0,p1=0,p2=0;
        char c[10];
        scanf("%d%d",&N,&M);
        block=pow(N,0.66666);
        for(int i=1;i<=N;i++) scanf("%d",&a[i]);
        for(int i=0;i<M;i++)
        {
            scanf("%s",c);
            if(c[0]=='Q')
            {
                scanf("%d%d",&q[p1].x,&q[p1].y);
                q[p1].num=p1;
                q[p1].tim=t;
                p1++;
            }
            else
            {
                t++;
                scanf("%d%d",&tw[t].x,&tw[t].y);
            }
    
        }
        sort(q,q+p1,cmp);
        int L=1,R=0,T=0;
        for(int i=0;i<p1;i++)
        {
            while(R<q[i].y)//往右走
            {
                solve(R+1,1);
                R++;
            }
            while(R>q[i].y)
            {
                solve(R,-1);
                R--;
            }
            while(L<q[i].x)
            {
                solve(L,-1);
                L++;
            }
            while(L>q[i].x)
            {
                solve(L-1,1);
                L--;
            }
            while(T<q[i].tim)
            {
                time_charge(i,T+1);
                T++;
            }
            while(T>q[i].tim)
            {
                time_charge(i,T);
                T--;
            }
            ans1[q[i].num]=ans;
        }
        for(int i=0;i<p1;i++) printf("%d
    ",ans1[i]);
        return 0;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    一周好文(15)
    一周好文(13)
    宏定义中的 "#" 和 "##"
    一周好文(14)
    CCRenderTexture崩溃问题分析
    C++反射机制的实现(转)
    一周好文(16)
    opengl on mac
    uthash: a hash table for C strcutures
    CC3LineNode线条变色的问题
  • 原文地址:https://www.cnblogs.com/caijiaming/p/10846914.html
Copyright © 2011-2022 走看看