BZoj 1293 生日礼物(小顶堆)

传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27400

Anayse:小顶堆;

1 1 5     - >    1 3 5     ->    3 5 7    ->     5 7 8

pop(1)    p(1)      p(3)       最优解。

每次剔除堆顶,然后换push与堆顶相同种类的珠子,由于单调,,距离会被缩短,于是找出最优解。详见上式。

push()  log(n)

so,复杂度 nlog(n).

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#define INF 0x7fffffff
#define SUP 0x80000000
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;

typedef long long LL;
const int N=100007;

int **a;
int nu[100];

struct node{
    int id,pos;
    node(int a,int b):id(a),pos(b){};
    bool operator <(node a) const
    {
        return pos<a.pos;
    }
};
vector<node> aa;

int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)==2)
    {
        mem(nu,0);
        priority_queue<int,vector<int>,less<int> > que;
        a=new int *[k+1];
        int num;
        for(int i=1;i<=k;i++)
        {
            scanf("%d",&num);
            a[i]=new int[num+1];
            nu[i]=a[i][0]=num;
            for(int j=1;j<=num;j++)
                scanf("%d",&a[i][j]);
        }

        int cnt=k;
        for(int i=1;i<=k;i++)  //构造初始堆
        {
            aa.push_back(node(i,a[i][1]));
            nu[i]=2;
        }
        int ans=INF;
        while(cnt<=n)   //依次剔除堆顶
        {
            sort(aa.begin(),aa.end());
            ans=min(ans,aa[k-1].pos-aa[0].pos);
            int ii=aa[0].id;
            if(nu[ii]>a[ii][0]){
                break;
            }
            aa[0]=node(ii,a[ii][nu[ii]++]);
            cnt++;
        }

        printf("%d\n",ans);

    }
    return 0;
}
时间: 2024-10-06 20:34:42

BZoj 1293 生日礼物(小顶堆)的相关文章

wikioi 1245 小顶堆

题目描述 Description 有两个长度为 N 的序列 A 和 B,在 A 和 B 中各任取一个数可以得到 N^2 个和,求这N^2 个和中最小的 N个. 输入描述 Input Description 第一行输入一个正整数N:第二行N个整数Ai 且Ai≤10^9:第三行N个整数Bi, 且Bi≤10^9 输出描述 Output Description 输出仅一行,包含 n 个整数,从小到大输出这 N个最小的和,相邻数字之间用 空格隔开. 样例输入 Sample Input 5 1 3 2 4

heap c++ 操作 大顶堆、小顶堆

在C++中,虽然堆不像 vector, set 之类的有已经实现的数据结构,但是在 algorithm.h 中实现了一些相关的模板函数.下面是一些示例应用 http://www.cplusplus.com/reference/algorithm/pop_heap/ #include <iostream> #include <algorithm> // make_heap(), pop_heap(), push_heap() #include <vector> using

POJ3253 Fence Repair 小顶堆+贪心

给了你N个木棒,求把他们组装成一根需要的最小花费,每次只能选两根组装在一起,需要的花费为两个木棒之和, 以前遇到过把一整根切开的,那个是DP,这个则有些类似,可是大胆的猜测了一下,直接每次选取所有木棒中最短的两根,这样就可以了,那么贪心是适用的,但是数量很多,而且两根最短的组装好了得插回去,这样不可能每次都排序吧, 这题首先优先队列肯定是可以做的, 最小堆也是可以的,每次都选出堆里的最小的两个求和再放回去即可 队列本身也就是堆吧,所以差别不大,但是没用过最小堆最大堆的 所以用一次把 #inclu

python 大顶堆 小顶堆

http://www.coder4.com/archives/3844 需1求:给出N长的序列,求出TopK大的元素,使用小顶堆,heapq模块实现. import heapq import random class TopkHeap(object): def __init__(self, k): self.k = k self.data = [] def Push(self, elem): if len(self.data) < self.k: heapq.heappush(self.data

wikioi 2573 大顶堆与小顶堆并用

题目描述 Description 我们使用黑匣子的一个简单模型.它能存放一个整数序列和一个特别的变量i.在初始时刻,黑匣子为空且i等于0.这个黑匣子能执行一系列的命令.有两类命令: ADD(x):把元素x放入黑匣子:GET:把i加1的同时,输出黑匣子内所有整数中第i小的数.牢记第i小的数是当黑匣子中的元素已非降序排序后位于第i位的元素. 下面的表6_4是一个11个命令的例子: 表6_4 编号 命令 i 黑匣子内容 输出 1 ADD(3) 0 3 2 GET 1 3 3 3 ADD(1) 1 1,

优先级队列(小顶堆)的dijkstra算法

php实现迪杰斯特拉算法,并由小顶堆优化 1 <?php 2 3 class DEdge 4 { 5 public $nextIndex, $length; 6 7 public function __construct($nextIndex, $length) 8 { 9 $this->nextIndex = $nextIndex; 10 $this->length = $length; 11 } 12 } 13 14 class DNode 15 { 16 public $index

剑指offer:数据流中的中位数(小顶堆+大顶堆)

1. 题目描述 /** 如何得到一个数据流中的中位数? 如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值. 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值. 我们使用 Insert()方法读取数据流,使用 GetMedian()方法获取当前读取数据的中位数. */ 2. 思路 /** 最大堆和最小堆 * 每次插入小顶堆的是当前大顶堆中最大的数 * 每次插入大顶堆的是当前小顶堆中最小的数 * 这样保证小顶堆中的数永远大于等于大顶堆中的数(值

7-31 笛卡尔树 (25分)--判断二叉搜索树,小顶堆

先初步判断是否满足二叉搜索树和小顶堆(针对每一颗最小的子树),如果都满足,进一步判断整棵树是否满足. 1 #include <iostream> 2 #include <string> 3 #include <cstring> 4 using namespace std; 5 typedef struct node 6 { 7 int K1; 8 int K2; 9 int L; 10 int R; 11 }node_arr[1001]; 12 node_arr s;

小顶堆,大顶堆

什么是字节序 在不同的计算机体系结构中,对于数据(比特.字节.字)等的存储和传输机制有所不同,因而引发了计算机领域中一个潜在但是又很重要的问题,即通信双方交流的信息单元应该以什么样的顺序进行传送.如果达不成一致的规则,计算机的通信与存储将会无法进行.目前在各种体系的计算机中通常采用的字节存储机制主要有两种:大端(Big-endian)和小端(Little-endian).这里所说的大端和小端即是字节序. MSB和LSB MSB是Most Significant Bit/Byte的首字母缩写,通常