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

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

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

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

    题解:

    做这道题之前不会带修改莫队,山神学会了之后手(嘴)把手(嘴)教我打代码。

    莫队算法先放下,带修改莫队是酱的:记下所有的修改,同时为每个询问加入一个时间标记,表示这个询问发生时修改到了哪一步。求解之前记录一个时间戳。每次求解一个询问时,先按普通莫队求解,然后查看当前时间戳和这个询问的标记,不一样的话就一个时间一个时间地改过去,同时修改答案。进行时间修改时,比如这道题,swap了修改的颜色和修改前的颜色,这样可以让之后发生时间倒流。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #define MXN 10000+1
    #define MXC 1000000+1
    struct Query{int l,r,t,id;}q[MXN];
    struct change{int p,co;}c[MXN];
    int block[MXN];
    bool cmp(Query A,Query B){
        if(block[A.l]==block[B.l]){
            if(A.r==B.r) return A.t<B.t;
            else return A.r<B.r;
        }
        else return block[A.l]<block[B.l];
    }
    int n,m,x,y;
    int qsum,csum;
    std::string p;
    int color[MXN];
    int man[MXC];
    int ans[MXN];
    void Change(int T,int i,int &temp){
        if(c[T].p>=q[i].l&&c[T].p<=q[i].r){
            man[color[c[T].p]]--;
            if(man[color[c[T].p]]==0) temp--;
            man[c[T].co]++;
            if(man[c[T].co]==1) temp++;
        }
        std::swap(color[c[T].p],c[T].co);
        return;
    }
    int main(){
        scanf("%d%d",&n,&m);
        int s=sqrt(n);
        for(int i=1;i<=n;i++){
            scanf("%d",&color[i]);
            block[i]=i/s;
        }
        while(m--){
            std::cin>>p;
            scanf("%d%d",&x,&y);
            if(p[0]=='Q'){
                q[qsum].l=x;
                q[qsum].r=y;
                q[qsum].id=qsum;
                q[qsum++].t=csum;
            }
            if(p[0]=='R'){
                c[++csum].p=x;
                c[csum].co=y;
            }
        }
        std::sort(q,q+qsum,cmp);
        int L=0,R=0,T=0,temp=0;
        for(int i=0;i<qsum;i++){
            while(L<q[i].l){man[color[L]]--;if(man[color[L]]==0) temp--;L++;}
            while(L>q[i].l){L--;man[color[L]]++;if(man[color[L]]==1) temp++;}
            while(R<q[i].r){R++;man[color[R]]++;if(man[color[R]]==1) temp++;}
            while(R>q[i].r){man[color[R]]--;if(man[color[R]]==0) temp--;R--;}
            while(T<q[i].t){T++;Change(T,i,temp);}
            while(T>q[i].t){Change(T,i,temp);T--;}
            ans[q[i].id]=temp;
        }
        for(int i=0;i<qsum;i++) printf("%d
    ",ans[i]);
        return 0;
    }
    代码

    PS:压行严重。

  • 相关阅读:
    排序算法-总览
    MySQL插入大批量测试数据
    【剑指offer】面试的流程
    并发编程-内置锁
    并发编程-使用线程安全类
    规约先行-(二十一)设计规约
    规约先行-(二十)服务器
    [转]web.xml什么时候被加载进内存的
    DOM和BOM的理解
    代理&反向代理
  • 原文地址:https://www.cnblogs.com/halifuda/p/8480451.html
Copyright © 2011-2022 走看看