【山东省选2008】郁闷的小J 平衡树Treap
输入
输出
样例输入
样例输出
提示
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<cstdlib>
- #include<ctime>
- using namespace std;
- const int N=;
- struct node
- {
- int x,lev,id;
- node *child[];
- }a[N*];
- node *pos,*root;
- void newnode(node *&r,int key,int ids)
- {
- r=pos++;
- r->child[]=r->child[]=NULL;
- r->x=key;
- r->id=ids;
- r->lev=rand();
- }
- int n;
- int gi()
- {
- int str=;char ch=getchar();
- while(ch>'' || ch<'')ch=getchar();
- while(ch>='' && ch<='')str=str*+ch-'',ch=getchar();
- return str;
- }
- int b[N];
- void rotate(node *&r,bool t)//0左旋 1右旋
- {
- node *y=r->child[!t];
- r->child[!t]=y->child[t];
- y->child[t]=r;
- r=y;
- }
- void insert(node *&r,int key,int ids)
- {
- if(r==NULL){newnode(r,key,ids);return ;}
- bool t=key>r->x;
- insert(r->child[t],key,ids);
- if(r->child[t]->lev<r->lev)rotate(r,!t);
- }
- void Delet(node *&r,int key,int ids)
- {
- if(r==NULL)return ;
- if(r->x==key && r->id==ids)
- {
- if(r->child[] && r->child[])
- {
- bool t=r->child[]->lev<r->child[]->lev;
- rotate(r,t);
- Delet(r->child[t],key,ids);
- }
- else
- {
- if(r->child[])r=r->child[];
- else r=r->child[];
- }
- }
- else
- {
- if(r->x!=key)Delet(r->child[key>r->x],key,ids);
- else {
- if(r->child[])Delet(r->child[],key,ids);
- if(r->child[])Delet(r->child[],key,ids);
- }
- }
- }
- int find(node *&r,int ls,int rs,int key)
- {
- if(r==NULL)return ;
- int sum=;
- if(r->x==key && r->id>=ls && r->id<=rs)sum++;
- if(r->x!=key)sum+=find(r->child[r->x<key],ls,rs,key);//先找到相同编号的书所在区域
- else {//然后爆搜
- if(r->child[])sum+=find(r->child[],ls,rs,key);
- if(r->child[])sum+=find(r->child[],ls,rs,key);
- }
- return sum;
- }
- void check(node *r)//检查的时候用
- {
- if(r==NULL)return ;
- printf("key=%d id=%d ",r->x,r->id);
- if(r->child[])printf("right=%d ",r->child[]->x);
- if(r->child[])printf("left=%d ",r->child[]->x);
- printf("\n");
- check(r->child[]);check(r->child[]);
- }
- int main()
- {
- int m;
- n=gi();m=gi();
- pos=a;
- for(int i=;i<=n;i++)
- {
- b[i]=gi();
- insert(root,b[i],i);
- }
- char f;int x,y,z;
- while(m--)
- {
- f=getchar();
- while(f!='Q' && f!='C')f=getchar();
- if(f=='C')//修改时先删再添加。
- {
- x=gi();y=gi();
- Delet(root,b[x],x);
- b[x]=y;
- insert(root,y,x);
- }
- else if(f=='Q')
- {
- x=gi();y=gi();z=gi();
- printf("%d\n",find(root,x,y,z));
- }
- }
- return ;
- }
然后是正解:离散化+Treap
设询问中C出现的次数为K,只需维护(K+N)个平衡树,用一个*root[N+K]来保存根节点即可实现。
注意是每一种书对应一颗平衡树,平衡树里保存的是在原数组出现的位置(即书柜号)。
然后Q L R X的话,先找到X对应的平衡树,再寻找编号在L和R之间的节点个数即可(可以用小于等于R的个数-小于L的个数)。
C X Y 设读入的数组为a[N],先在a[x]对应的树中删除编号为x的节点,再在Y对应的树中加入编号为X的节点。
代码如下:
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<cstdlib>
- #include<ctime>
- using namespace std;
- const int N=;
- struct node
- {
- int x,lev,size;
- node *child[];
- }a[N*];
- struct Ques
- {
- int flag,x,y,z;
- }q[N];
- int qm=;
- node *pos,*root[N];
- int s[N*];
- void newnode(node *&r,int key)
- {
- r=pos++;
- r->child[]=r->child[]=NULL;
- r->x=key;
- r->size=;
- r->lev=rand();
- }
- void updata(node *&r)
- {
- if(r)
- r->size=(r->child[]?r->child[]->size:)+(r->child[]?r->child[]->size:)+;
- }
- int n;
- int gi()
- {
- int str=;char ch=getchar();
- while(ch>'' || ch<'')ch=getchar();
- while(ch>='' && ch<='')str=str*+ch-'',ch=getchar();
- return str;
- }
- int b[N];
- void rotate(node *&r,bool t)//0左旋 1右旋
- {
- node *y=r->child[!t];
- r->child[!t]=y->child[t];
- y->child[t]=r;
- updata(r);
- r=y;
- updata(r);
- }
- void insert(node *&r,int key)
- {
- if(r==NULL){newnode(r,key);return ;}
- bool t=key>r->x;
- insert(r->child[t],key);
- if(r->child[t]->lev<r->lev)rotate(r,!t);
- updata(r);
- }
- void Delet(node *&r,int key)
- {
- if(r==NULL)return ;
- if(r->x==key)
- {
- if(r->child[] && r->child[])
- {
- bool t=r->child[]->lev<r->child[]->lev;
- rotate(r,t);
- Delet(r->child[t],key);
- }
- else
- {
- if(r->child[])r=r->child[];
- else r=r->child[];
- }
- }
- else Delet(r->child[key>r->x],key);
- updata(r);
- }
- int find(node *&r,int key)
- {
- if(r==NULL)return ;
- int sum=;
- if(r->x<=key){
- if(r->child[])sum+=r->child[]->size;
- sum++;
- }
- sum+=find(r->child[key>=r->x],key);
- return sum;
- }
- int py[N*],bel[N];
- int ny=;
- int midit(int x)//二分离散化以后该书对应的新编号
- {
- int mid,l=,r=ny,ans;
- while(l<=r)
- {
- mid=(l+r)>>;
- if(py[mid]<=x)ans=mid,l=mid+;
- else r=mid-;
- }
- return ans;
- }
- void check(node *r)//检查时用的,可以忽略
- {
- if(r==NULL)return ;
- printf("key=%d size=%d ",r->x,r->size);
- if(r->child[])printf("right=%d ",r->child[]->x);
- if(r->child[])printf("left=%d ",r->child[]->x);
- printf("\n");
- check(r->child[]);check(r->child[]);
- }
- int main()
- {
- int m;
- n=gi();m=gi();
- pos=a;
- for(int i=;i<=n;i++)s[i]=b[i]=gi();
- char f;int num=n;
- for(int i=;i<=m;i++)//现将数据全部读入,再编号 离散化。
- {
- f=getchar();
- while(f!='Q' && f!='C')f=getchar();
- if(f=='C')
- {
- q[i].x=gi();q[i].y=gi();
- s[++num]=q[i].y;
- }
- if(f=='Q')
- {
- q[i].x=gi();q[i].y=gi();q[i].z=gi();
- q[i].flag=;
- }
- }
- sort(s+,s+num+); //从小到大排序,方便编号
- for(int i=;i<=num;i++)if(s[i]!=s[i+])py[++ny]=s[i];//去重 该操作之后原数组对应的新编号就是py数组的下标。
- int tmp;
- for(int i=;i<=n;i++){
- tmp=midit(b[i]);
- bel[i]=tmp;//Bel为在书柜i位置的书对应的平衡树root[]中的下标。
- insert(root[tmp],i);
- }
- for(int i=;i<=m;i++)
- {
- if(!q[i].flag)
- {
- tmp=midit(q[i].y);
- Delet(root[bel[q[i].x]],q[i].x);
- bel[q[i].x]=tmp;
- insert(root[tmp],q[i].x);
- }
- else
- {
- tmp=midit(q[i].z);
- printf("%d\n",find(root[tmp],q[i].y)-find(root[tmp],q[i].x-));
- }
- }
- return ;
- }
【山东省选2008】郁闷的小J 平衡树Treap的更多相关文章
- 洛谷P2464 [SDOJ2008]郁闷的小J
洛谷P2464 [SDOJ2008]郁闷的小J 题目描述 小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他 ...
- [SDOI2008]郁闷的小J(分块)
[SDOI2008]郁闷的小J 题目描述 小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危 ...
- 洛谷P2464 [SDOI2008] 郁闷的小j [分块]
题目传送门 郁闷的小j 题目描述 小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也 ...
- 山东省选 郁闷的小J
小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的. 具体说来,书架由 ...
- P2464 [SDOI2008]郁闷的小J
题目描述 小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的. 具体说 ...
- fhqtreap - Luogu 2464 [SDOI2008]郁闷的小J
[SDOI2008]郁闷的小JJ 题目描述 小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的 ...
- 2018.09.26 洛谷P2464 [SDOI2008]郁闷的小J(map+vector)
传送门 本来出题人出出来想考数据结构的. 但是我们拥有map+vector/set这样优秀的STL,因此直接用map离散化,vector存下标在里面二分找答案就行了. 代码: #include< ...
- 【洛谷 P2464】[SDOI2008]郁闷的小J(线段树)
题目链接 这题我很久之前用分块写过,没写出来.. 今天又看到了,于是下决心把这题做出来. 这次我用线段树写的,直接对每本书的编号Hash一下然后离散化然后各建一棵线段树,维护当前编号在某个位置有没有书 ...
- HUST-1407 郁闷的小J
离线做法:分别处理每个编号上的各种询问和操作,接着就能用树状数组维护. #include <cstdlib> #include <cstdio> #include <cs ...
随机推荐
- 分享小知识:善用Group By排序
以下列举了公用表/临时表/聚合函数三个因素为例子(覆盖索引因素除外,有利用此类索引都会以索引顺序) 环境: Microsoft SQL Server 2014 (SP1-GDR) (KB319472 ...
- jump堡垒机配置使用
一.用户管理 1)添加用户 点击用户管理 —> 查看用户 —> 添加用户 输入要添加的用户名,姓名,权限,Mail,并且发送邮件 —> 保存 查看添加的用户 查看用户邮件 邮件中包含 ...
- Oh, my god令人头痛的“对象”--------C#数据类型
1.C#常用的数据类型: ①整型 int ②浮点型 float ③双精度型 double ④字符串 string ⑤布尔类型 ...
- [原创]ASM动态修改JAVA函数之函数字节码初探
ASM是非常强大的JAVA字节码生成和修改工具,具有性能优异.文档齐全.比较易用等优点.官方网站:http://asm.ow2.org/ 要想熟练的使用ASM,需要对java字节码有一定的了解,本文重 ...
- 使文字在div中水平和垂直居中的的css样式为,四个边分别设置阴影样式
text-align:center; /*水平居中*/ line-height: 20px; /*行距设为与div高度一致*/ HTML元素 <div>水平垂直居中</div> ...
- iOS开发之UICollectionViewController
1.概述 UICollectionView控件主要是用来做九宫格的,类似于android中的GridView控件.其用法与UITableView一样,首先要使控制器遵守数据源协议,再将控制器设置为UI ...
- Memcached十问十答
1.Memcached是什么,有什么作用? Memcached是一种纯内存的,key-value,CS架构的数据库服务软件,主要用于数据库,web服务器的缓存,以减小数据库,web服务器的访问压力,尤 ...
- java做帐户登录失败锁定
对于连续失败登录应用系统5次的帐号,需锁定该帐号至少30分钟不允许登录. 这里也用简单的map集合进行判定,功能能实现,但并不是很完美,不用更改数据库的表字段 1.首先建立一个用户登陆失败的实体类 p ...
- iOS关于友盟分享弹不出面板问题
在程序代理类中声明 [NSThread sleepForTimeInterval:10];//设置启动页面时间 [self.window makeKeyAndVisible]; [[UMSocialM ...
- Weblogic+apache多虚拟主机
p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; f ...