【poj1442】Black Box
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 10890 | Accepted: 4446 |
Description
ADD (x): put element x into Black Box;
GET: increase i by 1 and give an i-minimum out of all integers containing in the Black Box. Keep in mind that i-minimum is a number located at i-th place after Black Box elements sorting by non- descending.
Let us examine a possible sequence of 11 transactions:
Example 1
N Transaction i Black Box contents after transaction Answer
(elements are arranged by non-descending)
1 ADD(3) 0 3
2 GET 1 3 3
3 ADD(1) 1 1, 3
4 GET 2 1, 3 3
5 ADD(-4) 2 -4, 1, 3
6 ADD(2) 2 -4, 1, 2, 3
7 ADD(8) 2 -4, 1, 2, 3, 8
8 ADD(-1000) 2 -1000, -4, 1, 2, 3, 8
9 GET 3 -1000, -4, 1, 2, 3, 8 1
10 GET 4 -1000, -4, 1, 2, 3, 8 2
11 ADD(2) 4 -1000, -4, 1, 2, 2, 3, 8
It is required to work out an efficient algorithm which treats a given sequence of transactions. The maximum number of ADD and GET transactions: 30000 of each type.
Let us describe the sequence of transactions by two integer arrays:
1. A(1), A(2), ..., A(M): a sequence of elements which are being included into Black Box. A values are integers not exceeding 2 000 000 000 by their absolute value, M <= 30000. For the Example we have A=(3, 1, -4, 2, 8, -1000, 2).
2. u(1), u(2), ..., u(N): a sequence setting a number of elements which are being included into Black Box at the moment of first, second, ... and N-transaction GET. For the Example we have u=(1, 2, 6, 6).
The Black Box algorithm supposes that natural number sequence u(1), u(2), ..., u(N) is sorted in non-descending order, N <= M and for each p (1 <= p <= N) an inequality p <= u(p) <= M is valid. It follows from the fact that for the p-element of our u sequence
we perform a GET transaction giving p-minimum number from our A(1), A(2), ..., A(u(p)) sequence.
Input
Output
Sample Input
7 4
3 1 -4 2 8 -1000 2
1 2 6 6
Sample Output
3
3
1
2
Source
【题解】
一开始看错题目,以为是把i加入到平衡树中,然后在平衡树中把i的值加1,然后调整i在平衡树中的位置,然后再输出第i小的值。。。
所以程序中多了一个删除平衡树中某个点的操作。(就当做学习了);
真正的题意是,每次询问的时候递增i就好,然后输出第i小的数(这个i并不在平衡树里面!);
用的是sbt树。
sbt树因为本身就是用size来保持平衡的,所以求第k小的数的时候很方便;
/*
关于这个程序中的删除操作。需要用递归来实现。可能删除了某一个数字之后,拿来替换的节点也要进行复杂度删除操作(但是操作是相同的);具体的实现方式看程序;
*/
【代码】
#include <cstdio> int l[100000],r[100000],size[100000],totn = 0,key[100000],root =0;
int a[40000],b[40000]; void right_rotation(int &t) // 右旋代码。
{
int k = l[t];//先将根节点的左儿子提取出来。
l[t] = r[k];//然后把根节点的左儿子的右子树接在根节点的左子树位置
r[k] = t;//然后把原来的根节点的左儿子往右上旋转代替原来的根节点成为新的根节点。
size[k] = size[t];//新的根节点等于原来的根节点的大小
size[t] = size[l[t]]+size[r[t]]+1;//l[t]就是被转移过来的r[k(原来的)]。然后t的右子树是没有发生变化的。
t = k;//新的根节点变成了t。
} void left_rotation(int &t)//左旋代码
{
int k = r[t]; //先获取根节点的右儿子。
r[t] = l[k];//然后用根节点的右儿子的左子树来代替根节点的右子树;
l[k] = t;//然后把根节点的右儿子往左上的方向提上来代替原来的根节点
size[k] = size[t];//k成为了新的根节点,它的大小和原来的根节点是一样的。
size[t] = size[r[t]]+size[l[t]]+1;//t的左子树没有发生变化,然后右子树已经修改过了。直接加上相应的大小再加上自身即可
t = k;//根节点发生了变化变成了k
} void maintain(int &t,bool flag)//maintain函数,看SBT树的实现的话绕道。这里只写一下大概思路
{
if (flag) //往左调整
{
if (size[l[l[t]]] > size[r[t]])//这是/型的情况
right_rotation(t);
else
if (size[r[l[t]]] > size[r[t]])//这是<型的情况
{
left_rotation(l[t]);
right_rotation(t);
}
else
return;//如果都不是的话就结束递归
}
else
{
if (size[r[r[t]]] > size[l[t]])//这是\型的情况
{
left_rotation(t);
}
else
if (size[l[r[t]]] > size[l[t]])//这是>型的情况。
{
right_rotation(r[t]);
left_rotation(t);
}
else
return;
}
maintain(l[t],true);//可以这样理解,如果是\型,原来的根节点的右子树变成了原来的根节点的右儿子的左子树
//而原来的根节点的左子树不变。
//那么是原来的左子树比较大还是新的右子树比较大呢?
//当然是原来的左子树比较大,所以原来的根节点变成根节点的左儿子之后,调整的话应该是/型或<型的应该往左
maintain(r[t],false);//往右的同理。
maintain(t,true);//这两句是因为左右子树如果都发生了变化,需要重新维护一下根节点的子树。
maintain(t,false);//既然不知道方向,就两个方向都试试
} void insert(int &t,int data)//把data这个元素插入到平衡树中。
{
if (t==0)//如果是一个之前未到达过的节点则直接新创建一个节点
{
t=++totn;
l[t] = r[t] = 0;//把这个data记录在这个位置
size[t] = 1;//这个节点的大小为1
key[t] = data;
}
else
{
size[t]++;//否则就判断要往哪里走,不论往哪里走,以t为根节点的树的大小肯定递增了
if (data<key[t])//如果小于它就往左走
insert(l[t],data);
else//否则往右走
insert(r[t],data);
maintain(t,data<key[t]);//尝试调整平衡树,那个比较的表达式可以确定调整的方向。
}
} int k_th(int t, int k) //寻找k小数
{
if (size[l[t]]+1 == k)//如果比key[t]小的数的数目+1就是k,那么这个key[t]就是所求的数
return key[t];
else
if (size[l[t]] +1 > k)//如果比它小的数+1大于了k,那么就继续往左找第k小数
return k_th(l[t],k);
else
if (size[l[t]]+1<k)//如果比它小的数+1小于k,那么问题转换成往右找第(k-(size[l[t]]+1))小的数。
return k_th(r[t],k-(size[l[t]]+1));
} void de_lete(int data,int &t) //这是删除平衡树中某个节点的过程;
{
size[t]--;//因为这个节点肯定在以t为根的树下面。所以删除后,它的大小会递减。
if (key[t] == data)//如果找到了要删除的元素。
{
if (l[t] ==0 && r[t] == 0)//如果它没有左子树或右子树
t = 0;//那么就直接把这个节点置空
else
if (l[t] == 0 && r[t]!=0)//如果左子树为空,右子树不为空
t = r[t];//就把这个节点去掉,用右子树来接在下面。
else
if (l[t] != 0 && r[t] == 0)//如果左子树不为空,右子树为空
t = l[t];//则直接把这个节点去掉,把左子树接在下面。
else
if (l[t]!=0 && r[t]!=0)//如果左右子树都不为空。
{
int temp = r[t];//先记录这个节点的右儿子
while (l[temp]) temp = l[temp];//然后这个右儿子不断地往下找左儿子。
//这样可以找到一个合适的key放在t的位置。
//它满足<=r[t],且一定小于以r[t]为根的子树中的所有节点。满足平衡树定义。
key[t] = key[temp];//直接把那个合适的key值赋值到这个位置。
de_lete(key[temp],r[t]);//然后调用递归,把那个合适的key值所在的位置的节点去掉。
//不能单纯就去掉这个节点,因为其可能有右子树。另外,你一直往左下走,实际上没有递减
//size的值。。所以要重新从r[t]开始往下走。
/*
可以这样写;
小数据测试过。
int temp = r[t];
int pre = temp;
size[temp]--;
while (l[temp])
{
pre = temp;
temp = l[temp];
size[temp]--;
}
while结束之后temp肯定没有左子树了。
就判断一下有没有右子树;
if (r[temp]==0 && temp!=r[t])
l[pre] = 0;
else
if (r[temp] !=0)
l[pre] = r[temp];
这样就可以不用递归了。
*/
}
}
else
if (data<key[t])//如果要删除的值小于这个节点的key值,则往左走
de_lete(data,l[t]);
else//否则往右走。
de_lete(data,r[t]);
} int main()
{
//freopen("rush.txt","r",stdin);
//freopen("rush_out.txt","w",stdout);
int now = 0;
int n,m;
scanf("%d%d",&n,&m); //输入n和m
for (int i = 1;i <= n;i++) //把两个数组都输入
scanf("%d",&a[i]);
for (int i = 1;i <= m;i++)
scanf("%d",&b[i]);
int j = 1;//这是b数组的指针。
for (int i = 1;i <= n;i++)
{
insert(root,a[i]);//把ai这个元素插入到平衡树中
while (b[j]==i)//如果要询问的是在第i个,则输出询问
{
now++;//递增要输出的是第几小的树。。
printf("%d\n",k_th(root,now));//输出
j++;//指针指向下一个。
}
}
/*
下面这个东西是注释的内容。是我用来测试删除,添加和求第k小数的东西。
scanf("%s",op);
while (op[0]!='E')
{
scanf("%d",&a);
if (op[0] == 'A')
insert(root,a);
else
if (op[0] == 'F')
printf("%d\n",k_th(root,a));
else
if (op[0] == 'D')
de_lete(a,root);
scanf("%s",op);
}
*/
return 0;
}
【poj1442】Black Box的更多相关文章
- 【POJ1442】【Treap】Black Box
Description Our Black Box represents a primitive database. It can save an integer array and has a sp ...
- 【优先队列】POJ1442-Black Box
[思路] 建立一个小堆和一个大堆.大堆用来存放第1..index-1大的数,其余数存放在大堆,小堆的堆顶元素便是我们要求出的第index大的数.每次插入一个A(n),必须保证大堆中数字数目不变,故先插 ...
- 【hihocoder】 Magic Box
题目1 : Magic Box 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 The circus clown Sunny has a magic box. When ...
- 【前端】display: box布局教程 [转]
css display:box 新属性 一.display:box; 在元素上设置该属性,可使其子代排列在同一水平上,类似display:inline-block;. 二.可在其子代设置如下属性 ...
- 【转载】Virtual Box下配置Host-Only联网方式详解
其实网络这类相关的文章很多,我只是想结合自己的实际情况,把我的经验写下来,给那些需要的人们吧. 主机:windows 7 虚拟机:CentOS6.0 VirtualBox:4.2.0 虚拟机在安装好之 ...
- 【Ubuntu】Vritual Box 复制方式克隆
重装系统后之前安装的虚拟机的镜像全都不见了 ,因为重装系统盘C盘会全部重新被格式化. VtritualBox如果没有指定虚拟机存放位置,默认是会放在C盘的,C:\Users\Administrator ...
- 【Ruby】【高级编程】面向对象
# [[面向对象]]#[实例变量]=begin实例变量是类属性,它们在使用类创建对象时就编程对象的属性.每个对象的属性是单独赋值的,和其他对象之间不共享.在类的内部,使用@运算符访问这些属性,在类的外 ...
- 【BZOJ5138】[Usaco2017 Dec]Push a Box(强连通分量)
[BZOJ5138][Usaco2017 Dec]Push a Box(强连通分量) 题面 BZOJ 洛谷 题解 这题是今天看到萝卜在做然后他一眼秒了,我太菜了不会做,所以就来做做. 首先看完题目,是 ...
- 【荐】利用NAT、Host-Only双虚拟网卡,实现Virtual Box中CentOS5.x联网
一.虚拟机与主机互联,通常有三种方式,详细介绍请看: VMware虚拟机三种网络模式(Bridged,Nat,Host-only)区别详解 二.通过网络共享,Host-Only联网,详细案例请看: W ...
随机推荐
- C# 反射具体解释
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...
- wechat4j框架具体解释
发送消息: 基于上面access_token的逻辑,在构造发送消息对象的时候请依照例如以下代码. wechat4j和微信强力推荐的方法 CustomerMsg customerMsg = new Cu ...
- C8815 用 USB网卡(Asix AX88772 )上网
C8815 用 USB网卡(Asix AX88772 )上网 C8815不支持给USB外设供电,不过可以使用自供电的OTG线带动USB设备 C8815最新固件中没有Asix AX88772驱动,需要自 ...
- mmx-编译脚本
脚本目录位置 /home/zhangshuli/git2/vanzo_team/xulei/Mmx.py 在-/bin目录下,链接Mmx.py ln -sf ~/git2/vanzo_team/xul ...
- eclipse-hierarchyviewer 不能使用
今天安装了adt-bundle以后,发现hierarchyviewer不能用.点开了以后连手机没有效果.后来发现,还需要进入hierarchyviewer所在的sdk目录进行下权限的设置 chmod ...
- vanzo-代码共享平台地址
网页编辑.烧录代码 1.登录服务器 192.168.1.52 2.选择modules 3.选择builder 4.在 Project Name:填入要拉的项目名 选择版本:user,eng,userd ...
- 27. Spring Boot 部署与服务配置
转自“https://www.cnblogs.com/zhchoutai/p/7127598.html” Spring Boot 其默认是集成web容器的,启动方式由像普通Java程序一样,main函 ...
- LayUI-Table表格渲染
记项目中又一表格使用方法,项目首选是使用BootstrapTable的,但是经过多番查证与调试,始终没有把固定列的功能调试成功,找到的成功的例子原样照搬都不行,文件引入也都没有问题,实在搞不懂了,如果 ...
- error LNK2001: unresolved external symbol "public: virtual
1) Mine solution : project-setting :static lib to shared dll .then ok. 找不到secondchar的定义, 你是否没有把包含sec ...
- call.apply.冒充对象继承
call方法:让调用对象执行,然后第一参数是谁.调用对象的this就改变,指向谁,后边跟参数,依次对应传入 apply方法:让调用对象执行,然后第一参数是谁.调用对象的this就改变指向是谁,后边跟参 ...