#bzoj1846

来源:互联网 发布:js清除浏览器缓存数据 编辑:程序博客网 时间:2024/06/08 14:54

问题 A(1846): 【山东省选】郁闷的小J

时间限制: 4 Sec  内存限制: 512 MB

题目描述

小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架。虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的。

       具体说来,书架由N个书位组成,编号从1到N。每个书位放着一本书,每本书有一个特定的编码。

       小J的工作有两类:

  1. 图书馆经常购置新书,而书架任意时刻都是满的,所以只得将某位置的书拿掉并换成新购的书。
  2. 小J需要回答顾客的查询,顾客会询问某一段连续的书位中某一特定编码的书有多少本。

       例如,共5个书位,开始时书位上的书编码为1,2,3,4,5

       一位顾客询问书位1到书位3中编码为“2”的书共多少本,得到的回答为:1

       一位顾客询问书位1到书位3中编码为“1”的书共多少本,得到的回答为:1

       此时,图书馆购进一本编码为“1”的书,并将它放到2号书位。

       一位顾客询问书位1到书位3中编码为“2”的书共多少本,得到的回答为:0

       一位顾客询问书位1到书位3中编码为“1”的书共多少本,得到的回答为:2

……

       你的任务是写一个程序来回答每个顾客的询问。

输入

  第一行两个整数N,M,表示一共N个书位,M个操作。

       接下来一行共N个整数数A1,A2…AN,Ai表示开始时位置i上的书的编码。

       接下来M行,每行表示一次操作,每行开头一个字符

       若字符为‘C’,表示图书馆购进新书,后接两个整数A(1<=A<=N),P,表示这本书被放在位置A上,以及这本书的编码为P。

       若字符为‘Q’,表示一个顾客的查询,后接三个整数A,B,K(1<=A<=B<=N),表示查询从第A书位到第B书位(包含A和B)中编码为K的书共多少本。

(1<=N,M<=100000,所有出现的书的编码为不大于2147483647的正数。)

输出

对每一个顾客的查询,输出一个整数,表示顾客所要查询的结果。

样例输入

5 51 2 3 4 5Q 1 3 2Q 1 3 1C 2 1Q 1 3 2Q 1 3 1

样例输出

1102
朴素地强行直接按照位置来做平衡树是会超时的(后面会给出我的超时代码,可以先拿去交交看)

这里给出两种做法(正解):


法一:

将询问全部读入,离散化书的编号,

然后按照每书的种类不同,每种书建一棵树,树的内容为此种书摆放的位置。

每次C操作先删去原来位置上那种书的树中节点(数组持续更新记录位置上是哪种书),再在新书的树中加入节点

每次Q操作在书的树中累计区间数。


法二:

定义平衡树的顺序为:

1,书的编号种类。2,书的位置(这个注意看结构体里面的重载就比较清晰了)

按正常建树,

每次C操作把原来那个点删除后插入新点

每次Q操作就像查询排名一样后面的排名-前面的排名(注意是在之前的大小定义下)

想不通就想想这棵树的中序遍历,同一类书在中序里是挨在一起的说。


给出两种代码:

Code:

法一:

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std; const int Max = 100005;const int INF = 0x3f3f3f3f; struct Pro{    int l, r, p;}Ask[Max];struct node{    int num, sum;    int lc, rc, h;}Tr[Max << 1]; int cnt, Pre, Suc;int Root[Max], B[Max], S[Max << 1], Shelf[Max]; void getint(int & num){    char c; int flg = 1;    num = 0;    while((c = getchar()) < '0' || c > '9')   if(c == '-')    flg = -1;    while(c >= '0' && c <= '9')   {   num = num * 10 + c - 48;    c = getchar();}    num *= flg;} int max(int a, int b){  return a < b ? b : a;}int min(int a, int b){  return a < b ? a : b;} void pushup(int & r){    Tr[r].sum = Tr[Tr[r].lc].sum + Tr[Tr[r].rc].sum + 1;    Tr[r].h = max(Tr[Tr[r].lc].h, Tr[Tr[r].rc].h) + 1;} int zig(int r){    int t = Tr[r].lc;    Tr[r].lc = Tr[t].rc, Tr[t].rc = r;    pushup(r), pushup(t);    return t;} int zag(int r){    int t = Tr[r].rc;    Tr[r].rc = Tr[t].lc, Tr[t].lc = r;    pushup(r), pushup(t);    return t;} int zigzag(int r){    Tr[r].rc = zig(Tr[r].rc);    return zag(r);} int zagzig(int r){    Tr[r].lc = zag(Tr[r].lc);    return zig(r);} void maintain(int & r){    if(Tr[Tr[r].lc].h == Tr[Tr[r].rc].h + 2){        int t = Tr[r].lc;        if(Tr[Tr[t].lc].h == Tr[Tr[r].rc].h + 1)    r = zig(r);        else if(Tr[Tr[t].rc].h == Tr[Tr[r].rc].h + 1)   r = zagzig(r);    }    else if(Tr[Tr[r].rc].h == Tr[Tr[r].lc].h + 2){        int t = Tr[r].rc;        if(Tr[Tr[t].rc].h == Tr[Tr[r].lc].h + 1)    r = zag(r);        else if(Tr[Tr[t].lc].h == Tr[Tr[r].lc].h + 1)   r = zigzag(r);    }    pushup(r);} void Insert(int & r, int val){    if(! r){        r = ++ cnt;        Tr[r].num = val;        Tr[r].h = Tr[r].sum = 1;        return ;    }    if(val < Tr[r].num)  Insert(Tr[r].lc, val);    else Insert(Tr[r].rc, val);    maintain(r);} int Dele(int & r, int val){    int tx;    if(Tr[r].num == val || (val < Tr[r].num && ! Tr[r].lc) || ( val > Tr[r].num && ! Tr[r].rc)){        if(! Tr[r].lc || ! Tr[r].rc){            tx = Tr[r].num;            r = Tr[r].lc + Tr[r].rc;            return tx;        }        else Tr[r].num = Dele(Tr[r].lc, val);    }    else {        if(val < Tr[r].num)  tx = Dele(Tr[r].lc, val);        else tx = Dele(Tr[r].rc, val);    }    maintain(r);    return tx;} int Search(int &r, int pos){    if(! r) return 0;    int sum = 0;    if(Tr[r].num <= pos){        if(Tr[r].lc)    sum += Tr[Tr[r].lc].sum;        ++ sum;    }    if(Tr[r].num <= pos) sum += Search(Tr[r].rc, pos);    else sum += Search(Tr[r].lc, pos);    return sum;} int main(){    int N, M, tot;    getint(N), getint(M);    for(int i = 1; i <= N; ++ i){        getint(B[i]);         S[i] = B[i];    }    char ord[5];    tot = N;    for(int i = 1; i <= M; ++ i){        scanf("%s", ord);        if(ord[0] == 'Q'){            getint(Ask[i].l), getint(Ask[i].r);            getint(Ask[i].p);            S[++ tot] = Ask[i].p;        }        else {            getint(Ask[i].l), getint(Ask[i].p);            Ask[i].r = -1;        }    }    sort(S + 1, S + tot + 1);    int len = unique(S + 1, S + tot + 1) - S;    int tmp;    for(int i = 1; i <= N; ++ i){        tmp = lower_bound(S + 1, S + 1 + len, B[i]) - S;        Shelf[i] = tmp;        Insert(Root[tmp], i);    }    for(int i = 1; i <= M; ++ i){        if(Ask[i].r != -1){            tmp = lower_bound(S + 1, S + 1 + len, Ask[i].p) - S;            printf("%d\n", Search(Root[tmp], Ask[i].r) - Search(Root[tmp], Ask[i].l - 1));        }        else {            tmp = lower_bound(S + 1, S + 1 + len, Ask[i].p) - S;            Dele(Root[Shelf[Ask[i].l]], Ask[i].l);            Shelf[Ask[i].l] = tmp;            Insert(Root[tmp], Ask[i].l);        }    }    return 0;}

法二:

#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int Max = 100005;const int INF = 0x3f3f3f3f;struct bk{    int biao, pos;    bk(){}    bk(int a, int b){biao = a, pos = b;}bool operator <(const bk & X)const{if(biao == X.biao)return pos < X.pos;return biao < X.biao;}bool operator == (const bk & X)const{return biao == X.biao && pos == X.pos;}};struct node{    bk num;    int lc, rc, h, sum;}Tr[Max << 1];int cnt;int Shelf[Max];void getint(int & num){    char c;    int flg = 1;    num = 0;    while((c = getchar()) < '0' || c > '9')    if(c == '-')    flg = -1;    while(c >= '0' && c <= '9')    {    num = num * 10 + c - 48;    c = getchar();}    num *= flg;}int max(int a, int b){    return a < b ? b : a;}int min(int a, int b){    return a < b ? a : b;}void pushup(int & r){    Tr[r].h = max(Tr[Tr[r].lc].h, Tr[Tr[r].rc].h) + 1;Tr[r].sum = Tr[Tr[r].lc].sum + Tr[Tr[r].rc].sum + 1;}int zig(int r){    int t = Tr[r].lc;    Tr[r].lc = Tr[t].rc, Tr[t].rc = r;    pushup(r), pushup(t);    return t;}int zag(int r){    int t = Tr[r].rc;    Tr[r].rc = Tr[t].lc, Tr[t].lc = r;    pushup(r), pushup(t);    return t;}int zigzag(int r){    Tr[r].rc = zig(Tr[r].rc);    return zag(r);}int zagzig(int r){    Tr[r].lc = zag(Tr[r].lc);    return zig(r);}void maintain(int & r){    if(Tr[Tr[r].lc].h == Tr[Tr[r].rc].h + 2){        int t = Tr[r].lc;        if(Tr[Tr[t].lc].h == Tr[Tr[r].rc].h + 1)    r = zig(r);        else if(Tr[Tr[t].rc].h == Tr[Tr[r].rc].h + 1)    r = zagzig(r);    }    else if(Tr[Tr[r].rc].h == Tr[Tr[r].lc].h + 2){        int t = Tr[r].rc;        if(Tr[Tr[t].rc].h == Tr[Tr[r].lc].h + 1)    r = zag(r);        else if(Tr[Tr[t].lc].h == Tr[Tr[r].lc].h + 1)    r = zigzag(r);    }    pushup(r);}void Insert(int & r, bk val){    if(! r){        r = ++ cnt;        Tr[r].num = val;        Tr[r].h = Tr[r].sum = 1;        return ;    }    if(val < Tr[r].num)    Insert(Tr[r].lc, val);    else Insert(Tr[r].rc, val);    maintain(r);}bk Dele(int & r, bk val){    bk tx;    if(Tr[r].num == val || (val < Tr[r].num && ! Tr[r].lc) || (Tr[r].num < val && ! Tr[r].rc)){        if(! Tr[r].lc || ! Tr[r].rc){            tx = Tr[r].num;            r = Tr[r].lc + Tr[r].rc;            return tx;        }        else Tr[r].num = Dele(Tr[r].lc, val);    }    else {        if(val < Tr[r].num)    tx = Dele(Tr[r].lc, val);        else tx = Dele(Tr[r].rc, val);    }    maintain(r);    return tx;}int Query(int r, bk val){if(! r)return 0;if(Tr[r].num < val)return Tr[Tr[r].lc].sum + 1 + Query(Tr[r].rc, val);return Query(Tr[r].lc, val);}int main(){    int R = 0, N, M, A, B, K;    getint(N), getint(M);    for(int i = 1; i <= N; ++ i){        getint(Shelf[i]);         Insert(R, bk(Shelf[i], i));    }    char ord[10];    while(M --){        scanf("%s", ord);        switch(ord[0]){            case 'Q':{                getint(A), getint(B), getint(K);                printf("%d\n", Query(R, bk(K, B)) - Query(R, bk(K, A)) + (Shelf[B] == K));                break;            }            case 'C':{                getint(A), getint(K);                Dele(R, bk(Shelf[A], A));Shelf[A] = K;                Insert(R, bk(K, A));                break;            }        }    }    return 0;}

超时的朴素代码。。。。如下(留做个纪念吧,还是打了一小会儿呢):

#include<iostream>#include<cstdio>#include<cstdlib>using namespace std;const int Max = 200005;const int INF = 0x3f3f3f3f;struct bk{    int biao, pos;    bk(){}    bk(int a, int b){biao = a, pos = b;}};struct node{    bk num;    int lc, rc, h;}Tr[Max];int cnt, Pre, Suc;void getint(int & num){    char c;    int flg = 1;    num = 0;    while((c = getchar()) < '0' || c > '9')    if(c == '-')    flg = -1;    while(c >= '0' && c <= '9')    {    num = num * 10 + c - 48;    c = getchar();}    num *= flg;}int max(int a, int b){    return a < b ? b : a;}int min(int a, int b){    return a < b ? a : b;}void pushup(int & r){    Tr[r].h = max(Tr[Tr[r].lc].h, Tr[Tr[r].rc].h) + 1;}int zig(int r){    int t = Tr[r].lc;    Tr[r].lc = Tr[t].rc, Tr[t].rc = r;    pushup(r), pushup(t);    return t;}int zag(int r){    int t = Tr[r].rc;    Tr[r].rc = Tr[t].lc, Tr[t].lc = r;    pushup(r), pushup(t);    return t;}int zigzag(int r){    Tr[r].rc = zig(Tr[r].rc);    return zag(r);}int zagzig(int r){    Tr[r].lc = zag(Tr[r].lc);    return zig(r);}void maintain(int & r){    if(Tr[Tr[r].lc].h == Tr[Tr[r].rc].h + 2){        int t = Tr[r].lc;        if(Tr[Tr[t].lc].h == Tr[Tr[r].rc].h + 1)    r = zig(r);        else if(Tr[Tr[t].rc].h == Tr[Tr[r].rc].h + 1)    r = zagzig(r);    }    else if(Tr[Tr[r].rc].h == Tr[Tr[r].lc].h + 2){        int t = Tr[r].rc;        if(Tr[Tr[t].rc].h == Tr[Tr[r].lc].h + 1)    r = zag(r);        else if(Tr[Tr[t].lc].h == Tr[Tr[r].lc].h + 1)    r = zigzag(r);    }    pushup(r);}void Insert(int & r, bk val){    if(! r){        r = ++ cnt;        Tr[r].num = val;        Tr[r].h = 1;        return ;    }    if(val.pos < Tr[r].num.pos)    Insert(Tr[r].lc, val);    else Insert(Tr[r].rc, val);    maintain(r);}bk Dele(int & r, int pos){    bk tx;    if(Tr[r].num.pos == pos || (pos < Tr[r].num.pos && ! Tr[r].lc) || (pos > Tr[r].num.pos && ! Tr[r].rc)){        if(! Tr[r].lc || ! Tr[r].rc){            tx = Tr[r].num;            r = Tr[r].lc + Tr[r].rc;            return tx;        }        else Tr[r].num = Dele(Tr[r].lc, pos);    }    else {        if(pos < Tr[r].num.pos)    tx = Dele(Tr[r].lc, pos);        else tx = Dele(Tr[r].rc, pos);    }    maintain(r);    return tx;}int Query(int R, int l, int r, int k){    if(! R)    return 0;    if(Tr[R].num.pos < l)    return Query(Tr[R].rc, l, r, k);    if(Tr[R].num.pos > r)    return Query(Tr[R].lc, l, r, k);    bool flg = 0;    if(Tr[R].num.biao == k)    flg = 1;    return flg + Query(Tr[R].lc, l, r, k) + Query(Tr[R].rc, l, r, k);}int main(){    int R = 0, N, M, x, A, B, K;    getint(N), getint(M);    for(int i = 1; i <= N; ++ i){        getint(x);         Insert(R, bk(x, i));    }    char ord[10];    while(M --){        scanf("%s", ord);        switch(ord[0]){            case 'Q':{                getint(A), getint(B), getint(K);                printf("%d\n", Query(R, A, B, K));                break;            }            case 'C':{                getint(A), getint(K);                Dele(R, A);                Insert(R, bk(K, A));                break;            }        }    }    return 0;}