zoukankan      html  css  js  c++  java
  • P1903 [国家集训队]数颜色 / 维护队列 [带修莫队]

    写这篇博客的主要目的是记录 带修莫队 的实现方法.

    /数颜色 / 维护队列


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

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

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

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


    正解部分
    普通莫队 的分块大小为 Nsqrt N, 按照 为第一关键字, 右端点 为第二关键字排序.

    带修莫队 的分块大小为 N23N^{frac{2}{3}},按照 为第一关键字,
    右端点 不在同一个块中, 按 右端点为第二关键字 排序, 否则按 操作时间 为第二关键字 排序 .

    其余就是莫队基础操作了, 这里不再赘述 .


    实现部分
    没什么好说的 …

    #include <bits/stdc++.h>
    const int maxn = 1000005;
    
    int read(){
            int flag = 1;
            char c;
            while (!isdigit(c = getchar())) if(c == '-') flag = -1;
            int sum = 0;
            while(isdigit(c)) sum = sum*10 + c - '0', c = getchar();
            return sum * flag;
    }
    
    int N, M, cnt, _cnt, Ans, Tong[maxn], A[maxn], _Ans[maxn];
    int block_size;
    
    struct Query{ int L, R, block, index, tim, ans; } Q[maxn];
    
    struct Revise{ int pos, v; } R[maxn];
    
    bool cmp(const Query &a, const Query &b){
            if(a.block != b.block) return a.block < b.block;
            else if(a.R / block_size != b.R / block_size) return a.R < b.R; // WRONG  带修改莫队的理解
            return a.tim < b.tim;
    }
    
    bool _cmp(const Query &a, const Query &b){ return a.index < b.index; }  // 没有加取址符号,速度慢
    
    int LL, RR;
    void Change(int tim){
            int pos = R[tim].pos, v = R[tim].v;
            if(LL <= pos && pos <= RR){
                    Ans -= !-- Tong[A[pos]];
                    Ans += !Tong[v] ++;
            }
            R[tim].v ^= A[pos] ^= R[tim].v ^= A[pos];
    }
    
    int main(){
            N = read(), M = read();
            block_size = std::pow(N, 2.0/3);
            for(register int i = 1; i <= N; i ++) A[i] = read();
            char s[2];
            for(register int i = 1; i <= M; i ++){ 
                    scanf(" %s", s);
                    if(s[0] == 'Q'){ 
                            cnt ++;
                            Q[cnt].L = read(), Q[cnt].R = read();
                            Q[cnt].block = Q[cnt].L / block_size + 1;
                            Q[cnt].index = cnt;
                            Q[cnt].tim = _cnt;
                    }else if(s[0] == 'R')
                            _cnt++, R[_cnt].pos = read(), R[_cnt].v = read();
            }
            std::sort(Q+1, Q+cnt+1, cmp);
            register int l = 1, r = 0, tim = 0;
            for(register int i = 1; i <= M; i ++){
                    LL = Q[i].L;
                    RR = Q[i].R;
                    while(l < LL) Ans -= !-- Tong[A[l ++]];
                    while(l > LL) Ans += !Tong[A[-- l]] ++;
                    while(r < RR) Ans += !Tong[A[++ r]] ++;
                    while(r > RR) Ans -= !-- Tong[A[r --]];
                    while(tim < Q[i].tim) Change(++ tim);
                    while(tim > Q[i].tim) Change(tim --);
                    Q[i].ans = Ans;
                    _Ans[Q[i].index] = Ans;
            }
            //std::cerr << (double)clock() / CLOCKS_PER_SEC << std::endl;
            for(register int i = 1; i <= cnt; i ++) printf("%d
    ", _Ans[i]);
            return 0;
    }
    
  • 相关阅读:
    农田开发 NOJ (已知N个点选取3个求最大三角形面积问题)
    农田开发 NOJ (已知N个点选取3个求最大三角形面积问题)
    农田开发 NOJ (已知N个点选取3个求最大三角形面积问题)
    农田开发 NOJ (已知N个点选取3个求最大三角形面积问题)
    数次统计 NOJ 1601
    数次统计 NOJ 1601
    数次统计 NOJ 1601
    数次统计 NOJ 1601
    微型计算机原理与接口技术实验1.3.1
    微型计算机原理与接口技术实验1.3.1
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822567.html
Copyright © 2011-2022 走看看