• [模板]分块/可修改莫队 (数颜色种类)


    模板题地址

    题目描述

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

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

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

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

    范围N,M <=10000   每个数都<=10^6

    刚学会莫队就说说莫队:一种离线处理询问区间的好办法,虽然看上去超级暴力,但是很快。

    把询问按左右端点排序,每次移动两个端点在O(1)的时间内更新答案即可。

    while(L<q[i].l){/*O(1)更新答案*/L++;}
    while(L>q[i].l){L--;/*O(1)更新答案*/}
    while(R<q[i].r){R++;/*O(1)更新答案*/}
    while(R>q[i].r){/*O(1)更新答案*/R--;}

    当然还要用到分块的优化。

    P.S.排序以左端点所在的块为第一关键字,右端点为第二关键字

    struct Node{
        int l,r,id;
        bool operator <(const Node a){
            if(belong[l]==belong[a.l])return r<a.r;
            else return belong[l]<belong[a.l];
        }
    }q[MAXN];

    感觉是不是暴力得让人难以接受=、=  , 就是好用!

    然而话说回来这个题带上了修改。

    之前没有修改我们排序的是一个(l,r)

    带了修改就不妨加上一维时间轴,排序这个(l,r,t)

    再按照朴素的方法做,问题就迎刃而解了。

    代码

    #include<bits/stdc++.h>
    #define MAXN 10010
    using namespace std;
    int N,M,Q,siz,tim,a[MAXN],belong[MAXN],ans[MAXN],color[100010],tmp;
    struct Node{
        int l,r,id,t;
        bool operator <(const Node a){
            if(belong[l]==belong[a.l]){
                if(r==a.r)return t<a.t;
                else return r<a.r;
            }
            else return belong[l]<belong[a.l];
        }
    }q[MAXN];
    struct change{
        int x,y;
    }c[MAXN];
    void Change(int now,int i){
        if(c[now].x>=q[i].l&&c[now].x<=q[i].r){
            color[a[c[now].x]]--;
            if(color[a[c[now].x]]==0)tmp--;
            if(color[c[now].y]==0)tmp++;
            color[c[now].y]++;
        }
        swap(a[c[now].x],c[now].y);
    }
    int main()
    {
        scanf("%d%d",&N,&M);
        siz=sqrt(N);
        for(int i=1;i<=N;i++)scanf("%d",&a[i]),belong[i]=(i-1)/siz+1;
        for(int i=1;i<=M;i++){
            int a,b;char s[5];
            scanf("%s%d%d",s,&a,&b);
            if(s[0]=='Q')
                    q[++Q]=(Node){a,b,Q,tim};
            else     c[++tim]=(change){a,b}; 
        }
        sort(q+1,q+Q+1);
        int L=0,R=0,now=0;
        for(int i=1;i<=Q;i++){
            while(L<q[i].l){color[a[L]]--;if(color[a[L]]==0)tmp--;L++;}
            while(L>q[i].l){L--;color[a[L]]++;if(color[a[L]]==1)tmp++;}
            while(R<q[i].r){R++;color[a[R]]++;if(color[a[R]]==1)tmp++;}
            while(R>q[i].r){color[a[R]]--;if(color[a[R]]==0)tmp--;R--;}
            while(now<q[i].t){now++;Change(now,i);}
            while(now>q[i].t){Change(now,i);now--;}
            ans[q[i].id]=tmp;
        }
        for(int i=1;i<=Q;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    Security 前端页面配置
    使用HttpSession获取用户信息
    开启使用Tonken记住我功能
    基于注解的方式发送和订阅消费消息
    通过Security提供的SecurityContextHolder获取登录用户信息
    RabbitMQ 基于API的方式发送和消费消息
    TypeScript declare Object Array Interface methods All In One
    js get Set the first item All In One
    macOS run VSCode from terminal All In One
    在线 Java 语言编程 All In One
  • 原文地址:https://www.cnblogs.com/Elfish/p/7697851.html
Copyright © 2020-2023  润新知