bzoj2453/2120 数颜色

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2120

http://www.lydsy.com/JudgeOnline/problem.php?id=2453

【题解】

带修改莫队,分块大小n^(2/3),总复杂度O(n^(5/3))

简单说下,就是按照开始block,结束block,时间顺序分别排序后,不仅按照两个端点像莫队那样做,还把时间也按莫队那样做,就是维护恰好到询问时间的所有修改。

# include <math.h>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 2e5 + 10, N = 2e6 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, m, a[M], t[M];
int BLOCK, bl[M];
struct pa {
    int x, y, t;
    pa() {}
    pa(int x, int y, int t) : x(x), y(y), t(t) {}
    friend bool operator < (pa a, pa b) {
        return bl[a.x] < bl[b.x] || (bl[a.x] == bl[b.x] && bl[a.y] < bl[b.y]) ||
               (bl[a.x] == bl[b.x] && bl[a.y] == bl[b.y] && a.t < b.t);
    }
}q[M];

struct paa {
    int x, oc, nc, t;
    paa() {}
    paa(int x, int oc, int nc, int t) : x(x), oc(oc), nc(nc), t(t) {}
}p[M];

int pn, qn, ans[M];

int c[N], cnt, L, R;

inline void add(int x) {
    ++ c[a[x]];
    if(c[a[x]] == 1) ++cnt;    
}

inline void del(int x) {
    -- c[a[x]];
    if(c[a[x]] == 0) --cnt;
}

inline void DEL(int x) {
    --c[x];
    if(c[x] == 0) --cnt;
}

inline void ADD(int x) {
    ++c[x];
    if(c[x] == 1) ++cnt;
}


int main() {
    cin >> n >> m;
    BLOCK = pow(n, 2.0/3.0);
    for (int i=1; i<=n; ++i) {
        scanf("%d", a+i); t[i] = a[i];
        bl[i] = (i-1)/BLOCK + 1;
    }
    char opt[23];
    for (int i=1, x, y; i<=m; ++i) {
        scanf("%s%d%d", opt, &x, &y);
        if(opt[0] == 'R') {
            p[++pn] = paa(x, t[x], y, i);
            t[x] = y;
        } else q[++qn] = pa(x, y, i);
        ans[i] = 0;
    }
    sort(q+1, q+qn+1);
    L = 1, R = 0;
    for (int i=1, j=1; i<=qn; ++i) {
        while(j <= pn && q[i].t > p[j].t) {
            if(L <= p[j].x && p[j].x <= R) DEL(p[j].oc), ADD(p[j].nc);
            a[p[j].x] = p[j].nc; ++j;
        }
        while(j-1 >= 1 && q[i].t < p[j-1].t) {
            --j; if(L <= p[j].x && p[j].x <= R) DEL(p[j].nc), ADD(p[j].oc);
            a[p[j].x] = p[j].oc;
        }
        while(R < q[i].y) ++R, add(R);
        while(R > q[i].y) del(R), --R;
        while(L > q[i].x) --L, add(L);
        while(L < q[i].x) del(L), ++L;
        ans[q[i].t] = cnt;
    }
    for (int i=1; i<=m; ++i) 
        if(ans[i]) printf("%d\n", ans[i]);
    return 0;
}
View Code

 

posted @ 2017-06-14 11:45  Galaxies  阅读(257)  评论(0编辑  收藏  举报