ZOJ 3888 Twelves Monkeys (优先队列+预处理)

来源:互联网 发布:董宇阳,知乎 编辑:程序博客网 时间:2024/04/30 17:14

ZOJ 3888 Twelves Monkeys (优先队列+预处理)

tags: acm


(题目链接)

其实是挺简单的题,就是要找次小值.但是我开始的时候没想到用优先队列,强行暴力维护TLE了两遍,优化矬了WA一次,无奈改用优先队列后又错了好几次,后来花了好长时间(真的很久)才发现忘记重载小于号了(那时候我就觉得自己是一个煞笔orz)最后终于AC.

题意:

有M个时间机器,每个时间机器能让你从x年回到y年( 1yxn50000 ).现在你有一次使用时间机器的机会,问有哪些年你有两种方法到达.每组输入有多个询问,每个询问输入当前年份.

解析:

假如当前年份为p,则可以使用所有x值大于等于p的时间机器.而在这些机器中,我们只需要关注y值最小的两个就好了.y的最小值到当前年份之间的年份可以访问一次,而y次小值到当前年份之间能被访问两次.因此整个问题就转化为找到x>=p的时间机器中y第二小的那个.需要注意的是存在次小值大于p的情况.由于询问较多,我们可以先进行一次预处理,得到[1,n]范围内的所有p值对应的答案,将其存在ans[p]中,询问时输出对应的答案即可.

据说还可以用线段树(主席树)来做,不过我不是很明白,也没再多花时间了.

代码:

运行时间:550ms

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#define MAXN    50000+100using namespace std;struct E{    int from, to;}arc[MAXN];bool operator < (E a, E b){    if (a.from != b.from)        return a.from > b.from;    return a.to < b.to;}struct node{    int x;    node(int xx=0) { x = xx; }}nnode;bool operator < (node a, node b){    return a.x>b.x;}int ans[MAXN];int main(){    int N, M, q;    while (scanf("%d%d%d", &N, &M, &q) != EOF)    {        for (int i = 0; i < M; i++)        {            scanf("%d%d", &arc[i].from, &arc[i].to);        }        sort(arc, arc + M);        priority_queue<node> Q;        memset(ans, 0, sizeof(ans));        int pos = 0;        for (int i = N; i >= 0; i--)        {            while (pos < M && arc[pos].from >= i)            {                nnode.x = arc[pos++].to;                Q.push(nnode);            }            if (Q.size() >= 2)            {                int m1 = Q.top().x;                Q.pop();                int m2 = Q.top().x;                Q.pop();                if (m2 <= i)                {                    ans[i] = i - m2;                }                else                    ans[i] = 0;                Q.push(m1);                Q.push(m2);            }            else                ans[i] = 0;        }        int k;        for (int i = 0; i < q; i++)        {            scanf("%d", &k);            printf("%d\n", ans[k]);        }    }    return 0;}
0 0
原创粉丝点击