zoukankan      html  css  js  c++  java
  • 国家集训队 数颜色 [莫队]

    题目描述

    墨墨购买了一套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支画笔中共有几种不同颜色的画笔。

    输入输出样例

    输入样例#1:

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

    输出样例#1:

    4
    4
    3
    4

    说明

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

    本题可能轻微卡常数

    题解

    • 带修改莫队裸题

    • 学过莫队的人都知道,普通的莫队是不带修改操作的,但是后人在普通莫队的基础上,又加以改进,发明了带修改莫队,它的思想很简单易懂

    • 只有当出现查询操作时,前面的修改操作才有用,也就是说查询和修改两个操作是彼此独立的,因此,我们可以分别记录一下,哪些是查询,哪些是修改,然后普通莫队就行

    • 这样就够了吗?

    • 当然不行,我们还要记录一下到当前为止我们已经修改了几次,如果我们修改次数大于查询的序号,即改多了,我们就改回去,改少了就改过去

    • 举个例子,比如当前修改了3次,而最近的查询操作在第五次,我们就还需要进行第4,5次修改操作

    • 如果之前学过普通莫队的看这份代码应该没什么问题

    • 洛谷数据加强了,开(sqr(n))会T飞,开(7*sqr(n))快很多

    Code

    #include<bits/stdc++.h>
    #define in(i) (i=read())
    using namespace std;
    int read() {
        int ans=0,f=1; char i=getchar();
        while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
        while(i>='0' && i<='9') {ans=(ans<<1)+(ans<<3)+i-'0'; i=getchar();}
        return ans*f;
    }
    int n,m,qnum,cnum,tot;
    int c[1000010],cnt[1000010],ans[1000010],where[1000010];
    struct change {
        int pos,col;
    }a[1000010];
    struct query {
        int l,r,id,pre;
    }e[1000010];
    bool cmp(query a,query b) {
        if(where[a.l]!=where[b.l]) return where[a.l]<where[b.l];
        if(where[a.r]!=where[b.r]) return where[a.r]<where[b.r];
        return a.pre<b.pre;
    }
    void add(int x) {
        cnt[c[x]]++;
        if(cnt[c[x]]==1) tot++;
    }
    void remove(int x) {
        cnt[c[x]]--;
        if(!cnt[c[x]]) tot--;
    }
    void work(int now,int i) {
        if(a[now].pos>=e[i].l && a[now].pos<=e[i].r) {
            if(--cnt[c[a[now].pos]]==0) tot--;
            if(++cnt[a[now].col]==1) tot++;
        }
        swap(a[now].col,c[a[now].pos]);
    }
    int main()
    {
        in(n); in(m);
        int block=sqrt(n)*7;
        for(int i=1;i<=n;i++) {in(c[i]); where[i]=(i-1)/block+1;}
        for(int i=1;i<=m;i++) {
            char op; cin>>op;
            if(op=='Q') {
                in(e[++qnum].l); in(e[qnum].r);
                e[qnum].id=qnum;
                e[qnum].pre=cnum;
            }
            else {
                in(a[++cnum].pos); in(a[cnum].col);
            }
        }
        sort(e+1,e+1+qnum,cmp);
        for(int i=1,curl=1,curr=0,now=0;i<=qnum;i++) {
            int l=e[i].l, r=e[i].r;
            while(curl<l) remove(curl++);
            while(curl>l) add(--curl);
            while(curr<r) add(++curr);
            while(curr>r) remove(curr--);
            while(now<e[i].pre) work(++now,i);
            while(now>e[i].pre) work(now--,i);
            ans[e[i].id]=tot;
        }
        for(int i=1;i<=qnum;i++) printf("%d
    ",ans[i]);
        return 0;
    }
    

    边界问题

    最开始now=0,所以先增再执行
    最后此时now不符合条件,所以先执行再减

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    haoop 断电后导致block文件损坏
    笔记本上小固态硬盘的使用
    centos 7安装部署docker
    用msbuild构建应用
    清风注解-Swift程序设计语言:Point11~15
    清风注解-Swift程序设计语言:Point6~10
    清风注解-Swift程序设计语言
    享骑电单车投诉
    yaf不输出致命错误(Fatal error)的原因(之一)
    如何面试 PHP 工程师?
  • 原文地址:https://www.cnblogs.com/real-l/p/9210936.html
Copyright © 2011-2022 走看看