注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

TsReaper的博客

一起来玩算法竞赛吧~

 
 
 
 
 

日志

 
 

[题解][NOI导刊2010提高(06)]黑匣子  

2015-06-29 14:00:24|  分类: 题解 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
[好题] 关键字:双堆技巧。

Link&Limit


        [洛谷1801]  [codevs2573]
        时间限制:1000ms  空间限制:65536kb

Description


        Black Box是一种原始的数据库。它可以储存一个整数数组,还有一个特别的变量i。最开始的时候Black Box是空的.而i等于0。这个Black Box要处理一串命令。
        命令只有两种:
        ADD(x):把x元素放进BlackBox;
        CET:i加l,然后输出Blackhox中第i小的数。
        记住:第i小的数,就是Black Box里的数的按从小到大的顺序排序后的第i个元素。例如:
        我们来演示一下一个有11个命令的命令串。(如下图所示)
[题解][NOI导刊2010提高(06)]黑匣子 - TsReaper - TsReaper的博客
        现在要求找出对于给定的命令串的最好的处理方法。ADD和GET命令分别最多200000个。现在用两个整数数组来表示命令串:
        1.A(1),A(2),…A(M):一串将要被放进Black Box的元素。每个数都是绝对值不超过2000000000的整数,M ≤ 200000。例如上面的例子就是A=(3,1,一4,2,8,-1000,2)。
        2.u(1),u(2),…u(N):表示第u(j)个元素被放进了Blaek Box里后就出现一个GET命令。例如上面的例子中u=(l,2,6,6)。输入数据不用判错。

Input Format


        第一行,两个整数,M,N。
        第二行,M个整数,表示A(l)……A(M)。
        第三行,N个整数,表示u(l)…u(N)。

Output Format


        输出Black Box根据命令串所得出的输出串,一个数字一行。

Sample Input #1


7 4
3 1 -4 2 8-1000 2
1 2 6 6

Sample Output #1


3
3
1
2

Hint


        对于30%的数据,M≤10000;
        对于50%的数据,M≤100000;
        对于100%的数据,M≤200000。


        使用平衡树也可以完成这道题。但是题目中有一个值得关注的细节:
        “GET:i加1,然后输出Blackhox中第i小的数”
        如果GET操作不是按顺序询问,而是随机询问,那么平衡树自然是首选。但是GET操作是按顺序询问的,平衡树未免有点大材小用.......
        所以,我们建立两个堆,一个小根堆hmin,一个大根堆hmax。一开始读入数据时,将数据加入hmin。进行GET操作时,输出hmin的堆顶,并将其移入hmax。
        这样,hmax中存有的,就是当前黑箱中最小的i个数。当最新读入的数x比hmax的堆顶y要小时,说明x在新黑箱最小的i个数之中,相当于y的位置就被x挤掉了。那么就将y移回hmin。若x比y要大,则将x加入hmin。
        这种双堆的技巧,也适用于求多个连续区间的中位数。

#include <cstdio>
struct heap
{
    int h[200100],tot;
    heap() { tot = 0;}
   
    void add(int x)
    {
        int i = ++tot,j = i>>1;
        h[tot] = x;
        for(;i>1;i=j,j>>=1)
        {
            if(x>h[j]) {h[i] = h[j]; h[j] = x;}
            else break;
        }
    }
   
    void del()
    {
        int i = 1,j = 2,x = h[1] = h[tot--];
        for(;j<=tot;i=j,j<<=1)
        {
            if(j<tot) if(h[j+1]>h[j]) j++;
            if(x<h[j]) {h[i] = h[j]; h[j] = x;}
            else break;
        }
    }
}heap1,heap2;

int n,m,list[200010];

int main()
{
    int i,q;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++) scanf("%d",&list[i]);
    for(i=1;m;m--)
    {
        scanf("%d",&q);
        for(;i<=q;i++)
        {
            heap1.add(list[i]);
            heap2.add(-heap1.h[1]);
            heap1.del();
        }
        printf("%d\n",-heap2.h[1]);
        heap1.add(-heap2.h[1]);
        heap2.del();
    }
    return 0;
}

  评论这张
 
阅读(22)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018