HDU 5818 Joint Stacks(左偏树)

题目链接:点击打开链接

思路:

该题的关键是怎么把两个栈合并, 我们可以使用一种叫左偏树的数据结构, 满足堆的性质和集合的性质,支持在O(logn)的复杂度下进行删除堆顶元素, 插入一个元素,合并两个堆。

细节参见代码:

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> P;
const int maxn = 152400;
P v[maxn];
int tot, u, a, b,  l[maxn], r[maxn], d[maxn];//id[x]表示x所在树的编号
int Merge(int x, int y) {
    if(!x) return y;
    if(!y) return x;
    if(v[x] < v[y]) swap(x, y);
    r[x] = Merge(r[x], y);
    if(d[l[x]] < d[r[x]]) swap(l[x], r[x]);
    d[x] = d[r[x]] + 1;
    return x;
}
int init(P x) {
    tot++;
    v[tot] = x;
    l[tot] = r[tot] = d[tot] = 0;
    return tot;
}
int Insert(int x, P y) {
    return Merge(x, init(y));
}
P top(int x) {
    return v[x];
}
int pop(int x) {
    return Merge(l[x], r[x]);
}
char op[30], str[30], str2[30];
int val;
int main() {
    int kase = 0;
    int N;
    while(scanf("%d", &N), N) {
        memset(v, 0, sizeof(v));
        memset(l, 0, sizeof(l));
        memset(r, 0, sizeof(r));
        memset(d, 0, sizeof(d));
        tot = u = a = b = 0;
        printf("Case #%d:\n", ++kase);
        int posA = init(P(-1, -1));
        int posB = init(P(-2, -1));
        for(int i = 1; i <= N; ++i) {
            scanf("%s%s", op, str);
            if(op[1] == 'u') {
                scanf("%d", &val);
                if(str[0] == 'A') {
                    posA = Insert(posA, P(i, val));
                } else {
                    posB = Insert(posB, P(i, val));
                }
            }
            else if(op[1] == 'o') {
                P ans;
                if(str[0] == 'A') {
                    ans = top(posA);
                    posA = pop(posA);
                } else {
                    ans = top(posB);
                    posB = pop(posB);
                }
                printf("%d\n", ans.second);
            }
            else if(op[1] == 'e') {
                scanf("%s", str2);
                if(str[0] == 'A') {
                    posA = Merge(posA, posB);
                    posB = init(P(-i, -1));
                } else {
                    posB = Merge(posA, posB);
                    posA = init(P(-i, -1));
                }
            }
        }
    }
    return 0;
}
时间: 2025-01-07 19:42:19

HDU 5818 Joint Stacks(左偏树)的相关文章

HDU 5818 Joint Stacks(联合栈)

HDU 5818 Joint Stacks(联合栈) Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Description 题目描述 A stack is a data structure in which all insertions and deletions of entries are made at one end, called the "top" of

hdu 1512 Monkey King 左偏树

题目链接:HDU - 1512 Once in a forest, there lived N aggressive monkeys. At the beginning, they each does things in its own way and none of them knows each other. But monkeys can't avoid quarrelling, and it only happens between two monkeys who does not kn

HDU 5818 Joint Stacks

搞了第三个栈来表示合并之后的.偷懒写了一个优先队列. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #inc

HDU 1512 Monkey King ——左偏树

[题目分析] 也是堆+并查集. 比起BZOJ 1455 来说,只是合并的方式麻烦了一点. WA了一天才看到是多组数据. 盲人OI (- ̄▽ ̄)- Best OI. 代码自带大常数,比启发式合并都慢 [代码] #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <set> #include <map> #include <

HDU 5818 Joint Stacks ——(栈的操作模拟,优先队列)

题意:有两个栈A和B,有3种操作:push,pop,merge.前两种都是栈的操作,最后一种表示的是如果“merge A B”,那么把B中的元素全部放到A中,且满足先入后出的栈原则. 分析:显然,我们给每一个节点配备一个时间戳即可.我一开始的思路是直接开两个优先队列进行直接模拟,merge操作就是把一个栈的元素全部倾倒到另一个栈内,但是会出现的问题是,如果有一个状态A和B的元素都相当多了,并且反复的进行merge操作,那么每一次merge都意味着大量的元素进出,肯定会超时的.因此,我们需要优化,

HDU - 5818 Joint Stacks 想法题 关键

http://codeforces.com/problemset/problem/669/D 题意:n个数1~N围成一个圈.q个操作包括操作1:输入x, 所有数右移x.操作2:1,2位置上的数(swap(a[1], a[2])交换:3,4交换.... 题解:观察,发现所有奇数行为都是一样的,偶数同理,(对于操作1 两者相同,对于操作2 奇数位++,偶数位上--: 模拟1,2,即可,然后依次输出其它数字即可.(看清 ac代码: #define _CRT_SECURE_NO_WARNINGS #in

Monkey King HDU - 1512 (左偏树)

Monkey King HDU - 1512 忽然看到左偏树,挺简单的,抄了个模板题练练 1 //左偏树 2 #include <bits/stdc++.h> 3 using namespace std; 4 const int maxn = 100010; 5 struct Node{ 6 int val, dis, l, r; 7 }p[maxn]; 8 int f[maxn]; 9 int gf(int x){ 10 return x == f[x] ? f[x] : f[x] = gf

HDU 1512 并查集+左偏树

Monkey King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3105    Accepted Submission(s): 1330 Problem Description Once in a forest, there lived N aggressive monkeys. At the beginning, they e

左偏树

概要:左偏树是具有左偏性质的堆有序二叉树,它相比于优先队列,能够实现合并堆的功能. 先仪式型orzorzozr国家集训队论文https://wenku.baidu.com/view/515f76e90975f46527d3e1d5.html 左偏树的节点定义: 1 struct node { 2 int lc, rc, val, dis; 3 } LTree[maxn]; 左偏树的几个基本性质如下: 节点的键值小于等于它的左右子节点的键值 节点的左子节点的距离不小于右子节点的距离 节点的距离等于