zoukankan      html  css  js  c++  java
  • 数颜色

         题意:

      n个数,m个操作。

    •  查询区间[a,b]内不同数字数
    •  将某个数修改为c

      题解:

      带修改莫队。

        与普通莫队不同的就是要记录一下每个查询操作前有多少个修改操作,然后暴力修改或改回去。

      题目链接:https://www.luogu.org/problemnew/show/P1903

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define LL long long
    #define RI register int
    using namespace std;
    const int INF = 0x7ffffff ;
    const int S = 1e6 + 10 ;
    const int N = 10000 + 10 ;
    
    inline int read() {
        int k = 0 , f = 1 ; char c = getchar() ;
        for( ; !isdigit(c) ; c = getchar())
          if(c == '-') f = -1 ;
        for( ; isdigit(c) ; c = getchar())
          k = k*10 + c-'0' ;
        return k*f ;
    }
    
    struct Que {
        int l, r, ti, id ;
    }q[N] ;
    
    int n, m, qcnt = 0, rcnt = 0, hh[N], pp[1010], cc[1010], res[N], pos[N], num[S], ans = 0 ;
    int L = 1, R = 0, T = 0 ;
    
    inline bool cmp1(Que s,Que t) {  // 其实我也不知道怎么排序最快qaq 
        if(pos[s.l] == pos[t.l]) {
            if(pos[s.r] == pos[t.r]) return s.ti < t.ti ;
            return s.r < t.r ;
        } 
        return s.l < t.l ;
    }
    
    inline void add(int x) {
        if(!num[hh[x]]) ans ++ ;
        num[hh[x]] ++ ;
    }
    inline void del(int x) {
        num[hh[x]] -- ;
        if(!num[hh[x]]) ans -- ;
    }
    inline void addt(int t) {
        if(pp[t] >= L && pp[t] <= R) {
            num[hh[pp[t]]] -- ;
            if(!num[hh[pp[t]]]) ans -- ;
            if(!num[cc[t]]) ans ++ ;
            num[cc[t]] ++ ;
        }
        swap(hh[pp[t]],cc[t]) ;
        // 这是一步很神奇的操作
        // 因为记录每个位置的历史值显然是十分麻烦的。
        // 我们可以观察一个性质就是当一个修改操作被改回去时,就是原值变成修改值,修改值变成原值
        // 所以只要交换一下即可 
    }
    
    int main() {
        n = read(), m = read() ;
        int base = sqrt(n) ;
        for(int i=1;i<=n;i++) hh[i] = read(), pos[i] = (i-1)/base + 1 ;
        char cs ;
        for(int i=1;i<=m;i++) {
            cin>>cs ;
            if(cs == 'Q') {
                q[++qcnt].l = read(), q[qcnt].r = read() ;
                q[qcnt].ti = rcnt ; q[qcnt].id = qcnt ;
            } else {
                pp[++rcnt] = read(), cc[rcnt] = read() ;
            }
        }
        sort(q+1,q+qcnt+1,cmp1) ;
        for(int i=1;i<=qcnt;i++) {
            while(L < q[i].l) del(L++) ;
            while(L > q[i].l) add(--L) ;
            while(R < q[i].r) add(++R) ;
            while(R > q[i].r) del(R--) ; // 以上与普通莫队相同 
            while(T < q[i].ti) addt(++T) ;
            while(T > q[i].ti) addt(T--) ; // 为什么都是add操作呢?看看addt函数就知道了qwq 
            res[q[i].id] = ans ;
        }
        for(int i=1;i<=qcnt;i++) {
            printf("%d
    ",res[i]) ;
        }
        return 0 ;
    }

     PS:scanf读单字符时不忽略空格与换行符T_T,换用cin即可.

  • 相关阅读:
    Ubuntu 使用OpenCV 利用Makefile运行
    YOLOV3——PyTorch训练TensorFlowLite部署模型转换
    PyTorch——学习笔记
    opencv调用摄像头分辨率问题
    Dlib与Opencv中图像格式转换(matrix-Mat)
    Windows下 VS2015 + Dlib + CUDA环境搭建
    OpenCV——银行卡识别
    QT入门
    LeetCode——最长连续回文串
    数值分析--第四章--特征值特征向量计算(乘幂法)
  • 原文地址:https://www.cnblogs.com/zub23333/p/8545295.html
Copyright © 2011-2022 走看看