【BZOJ2120】数颜色(树套树+set)

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2120

题解:http://blog.sina.com.cn/s/blog_6e63f59e0101bm87.html

 

一开始懒得离散化,跑了7000+ms23333 宛如一个智障,可是出现了这么迷醉的情况、

2333果然还是要勤快一点 写个离散化啊

 

#include <set>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define MaxN 20010
#define MaxM 7000010
using namespace std;
int n, S = 0, m, tot = 0, N = 0;
int num[MaxN], da[MaxN], map[MaxN];
int root[MaxN], t1[MaxN], t2[MaxN];
int ls[MaxM], rs[MaxM], sum[MaxM];
char s[10];
set <int> q[MaxN];
struct rec{
    int l, r;
    char s[10];
}op[MaxN];
void Read_Data(){
    scanf("%d%d", &n, &m);
    for (int i = 0; i < MaxN; i++) q[i].insert(n+1), q[i].insert(0);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &num[i]);
        da[++tot] = num[i];
    }
    for (int i = 1; i <= m; i++){
        scanf("%s%d%d", op[i].s, &op[i].l, &op[i].r);
        if (op[i].s[0] != 'Q') da[++tot] = op[i].r;
    }
    sort(da+1, da+1+tot);
    map[++N] = da[1];
    for (int i = 2; i <= tot; i++)
        if (da[i] != da[i-1]) map[++N] = da[i];
}

int find(int x){
    int l = 1, r = N, mid;
    while (l < r) {
        mid = (l+r) >> 1;
        if (x <= map[mid]) r = mid;
        else l = mid+1;
    }
    return l;
}

void updata(int &x, int l, int r, int k, int c){
    int fa = x;  
    if (!x) x = ++S;
    ls[x] = ls[fa], rs[x] = rs[fa], sum[x] = sum[fa]+c;
    if (l == r) return;
    int mid = (l+r) >> 1;
    if (k <= mid) updata(ls[x], l, mid, k, c);
    else updata(rs[x], mid+1, r, k, c);
}

int lowbit(int x) {
    return x & (-x);
}

void updata(int x, int k, int c){
    for (int i = x; i <= n; i += lowbit(i)) updata(root[i], 0, n, k, c);
}

int query(int a, int b, int k){
    int l = 0, r = n, mid, ret = 0, len1 = 0, len2 = 0, t = 0;
    for (int i = a; i; i -= lowbit(i)) t1[++len1] = root[i];
    for (int i = b; i; i -= lowbit(i)) t2[++len2] = root[i];
    while (l < r){
        mid = (l+r) >> 1;
//        cout<<a<<" "<<b<<" t"<<b-a<<" l"<<l<<" r"<<r<<endl;
        if (k <= mid) {
            r = mid;
            for (int i = 1; i <= len1; i++) ret -= sum[rs[t1[i]]];
            for (int i = 1; i <= len2; i++) ret += sum[rs[t2[i]]];
            for (int i = 1; i <= len1; i++) t1[i] = ls[t1[i]];
            for (int i = 1; i <= len2; i++) t2[i] = ls[t2[i]];
        }
        else {
            l = mid+1;
            for (int i = 1; i <= len1; i++) t1[i] = rs[t1[i]];
            for (int i = 1; i <= len2; i++) t2[i] = rs[t2[i]];
        }
    }
    return ret;
}

void Solve(){
    int l, r, c;
    n++;
    for (int i = 1; i < n; i++) num[i] = find(num[i]), q[num[i]].insert(i);
    for (int i = 1; i < n; i++) updata(i, *q[num[i]].upper_bound(i), 1);//, updata(0, i, 1);
//    cout<<query(1, 6, 6); 
    for (int i = 1; i <= m; i++){
        int l = op[i].l, r = op[i].r;
        if (op[i].s[0] == 'Q'){
            printf("%d\n", query(l-1, r, r));
        }
        else {
            set<int>::iterator p;
            p = q[num[l]].lower_bound(l); p--;
            int t = *(p);
            if (t) {
                updata(t, l, -1);
                updata(t, *q[num[l]].upper_bound(l), 1);    
            }
            updata(l, *q[num[l]].upper_bound(l), -1);
            q[num[l]].erase(l);
            num[l] = find(op[i].r);
            q[num[l]].insert(l);
            p = q[num[l]].lower_bound(l); p--;
            t = *(p);
            if (t) {
                updata(t, l, 1);
                updata(t, *q[num[l]].upper_bound(l), -1);    
            }
            updata(l, *q[num[l]].upper_bound(l), 1);
        }
    }
}

int main(){
    Read_Data();
    Solve();
    return 0;
}

 

posted @ 2016-03-16 15:48  Lukaluka  阅读(401)  评论(0编辑  收藏  举报