AVL平衡树(山东省选 郁闷的小J)

来源:互联网 发布:ubuntu查看64位 32位 编辑:程序博客网 时间:2024/06/11 17:06

题目描述:

小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


这道题思维难度不大,很容易就可以想出平衡树的正解,难在实现。但其实,将平衡树的模板稍微修改即可过

题解:

这里给出两个思路,一种是对于每种书都做一个平衡树,按那个书的位置排序

第二种是按书的编号排序,编号相同用位置排序,这里采用的是第二种思路

这里是用了结构体重定义运算符来实现的,代码和模板简直一模一样。。。

code:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<cstdlib>#include<algorithm>  typedef long long LL;const int MAXN=200005;using namespace std;struct Temp{    int data,pos;    Temp(){}    Temp(int a,int b){        data=a,pos=b;    }    bool operator ==(const Temp &b)const{        return data==b.data&&pos==b.pos;    }    bool operator<(const Temp &b)const{        if(data==b.data) return pos<b.pos;        else return data<b.data;    }    bool operator>(const Temp &b)const{        if(data==b.data) return pos>b.pos;        else return data>b.data;    }    bool operator<=(const Temp &b)const{        return !(*this>b);    }    bool operator>=(const Temp &b)const{        return !(*this<b);    }};struct node{    int lc,rc,h,num;    Temp data;}tree[MAXN+5];int cnt,root,arr[MAXN],N,M;    inline void Read(int &Ret){    char ch;bool flag=0;    for(;ch=getchar(),ch<'0'||ch>'9';)if(ch=='-')flag=1;    for(Ret=ch-'0';ch=getchar(),'0'<=ch&&ch<='9';Ret=Ret*10+ch-'0');    flag&&(Ret=-Ret);}inline void update(int i){    tree[i].h=max(tree[tree[i].lc].h,tree[tree[i].rc].h)+1;    tree[i].num=tree[tree[i].lc].num+tree[tree[i].rc].num+1;}int zig(int i){    int t=tree[i].lc;    tree[i].lc=tree[t].rc;    tree[t].rc=i;    update(i); update(t);    return t;}int zag(int i){    int t=tree[i].rc;    tree[i].rc=tree[t].lc;    tree[t].lc=i;    update(i); update(t);    return t;}int zigzag(int i){    tree[i].rc=zig(tree[i].rc);    return zag(i);}int zagzig(int i){    tree[i].lc=zag(tree[i].lc);    return zig(i);}   void maintain(int &i){    if(tree[tree[i].lc].h==tree[tree[i].rc].h+2)    {        int t=tree[i].lc;        if(tree[tree[t].rc].h==tree[tree[i].rc].h+1) i=zagzig(i);        else if(tree[tree[t].lc].h==tree[tree[i].rc].h+1) i=zig(i);    }    else if(tree[tree[i].rc].h==tree[tree[i].lc].h+2)    {        int t=tree[i].rc;        if(tree[tree[t].lc].h==tree[tree[i].lc].h+1) i=zigzag(i);        else if(tree[tree[t].rc].h==tree[tree[i].lc].h+1) i=zag(i);    }    update(i);}void Insert(int &i,Temp x){    if(!i)    {        tree[++cnt].data=x;        tree[cnt].h=tree[cnt].num=1;        i=cnt; return;    }    if(x<=tree[i].data) Insert(tree[i].lc,x);    else Insert(tree[i].rc,x);    maintain(i); return;}Temp Delete(int &i,Temp x){    Temp res;    if(tree[i].data==x||(x>tree[i].data&&!tree[i].rc)||(x<tree[i].data&&!tree[i].lc))    {        res=tree[i].data;        if(!tree[i].rc||!tree[i].lc)            {i=tree[i].rc+tree[i].lc;return res;}        else tree[i].data=Delete(tree[i].lc,x);    }    else    {        if(x<tree[i].data) res=Delete(tree[i].lc,x);        else res=Delete(tree[i].rc,x);    }    maintain(i); return res;}int getrank(int i,Temp x){    if(!i) return 0;    if(x<=tree[i].data) return getrank(tree[i].lc,x);    else  return tree[tree[i].lc].num+1+getrank(tree[i].rc,x);}int Query(int a,int b,int num){    int x=getrank(root,Temp(num,b));    int y=getrank(root,Temp(num,a));    if(arr[b]==num) x++; return x-y;}int main(){    Read(N); Read(M);    for(int i=1;i<=N;i++)    {        scanf("%d",&arr[i]);        Insert(root,Temp(arr[i],i));    }    int a,b,k,p; char ord[5];    for(int i=1;i<=M;i++)    {        scanf("%s",ord);        switch(ord[0])        {            case 'C':                scanf("%d%d",&a,&p);                Delete(root,Temp(arr[a],a));                Insert(root,Temp(p,a));arr[a]=p;            break;              case 'Q':                scanf("%d%d%d",&a,&b,&k);                printf("%d\n",Query(a,b,k));                break;        }    }    return 0;}