您的位置:首页 > 其它

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

2017-07-12 19:10 169 查看
题目描述:

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

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

       小J的工作有两类:
图书馆经常购置新书,而书架任意时刻都是满的,所以只得将某位置的书拿掉并换成新购的书。
小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的正数。)
输出: 对每一个顾客的查询,输出一个整数,表示顾客所要查询的结果。

样例:

Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)
5 5
1 2 3 4 5
Q 1 3 2
Q 1 3 1
C 2 1
Q 1 3 2
Q 1 3 1


样例输出

1
1
0
2


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

题解:

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

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

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

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: