洛谷 [P3224] 永无乡
Treap 的合并
首先感谢 @Capella 的DeBug
其次,这是由一个 & 号引发的血案
注意对于所有修改操作都要 &
Treap的合并, 启发式合并,对于每一个节点都 insert ,注意垃圾回收
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int MAXN = 500005;
int init() {
    int rv = 0, fh = 1;
    char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') fh = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        rv = (rv<<1) + (rv<<3) + c - '0';
        c = getchar();
    }
    return fh * rv;
}
int pool[MAXN], top, n, m, id[MAXN], q;
struct UFS {
    int fa[MAXN];
    void unit() {
        for(int i = 1; i <= n; i++) fa[i] = i;
    }
    int find(int x) {
        if(x != fa[x]) return fa[x] = find(fa[x]);
        return fa[x];
    }
}ufs;
struct node{
    int val, dat, num, size, l, r;
}a[MAXN];
struct Treap{
    int New(int x, int num) {
        int ret = pool[++top];
        a[ret].val = x;
        a[ret].num = num;
        a[ret].dat = rand();
        a[ret].size = 1;
        a[ret].l = a[ret].r = 0;
        return ret;
    }
    void del(int &rt) {pool[top--] = rt;rt = 0;}
    void PushUp(int rt) {
        a[rt].size = a[a[rt].l].size + a[a[rt].r].size + 1;
    }
    void zig(int &rt) {
        int nxt = a[rt].l;
        a[rt].l = a[nxt].r; a[nxt].r = rt; rt = nxt;
        PushUp(a[rt].r);
        PushUp(rt);
    }
    void zag(int &rt) {
        int nxt = a[rt].r;
        a[rt].r = a[nxt].l; a[nxt].l = rt; rt = nxt;
        PushUp(a[rt].l);
        PushUp(rt);
    }
    void Insert(int &rt, int x, int num) {
        if(!rt) {
            rt = New(x, num);
            return;
        }
        if(x < a[rt].val) {
            Insert(a[rt].l, x, num);
            if(a[a[rt].l].dat > a[rt].dat) zig(rt);
        }else {
            Insert(a[rt].r, x, num);
            if(a[a[rt].r].dat > a[rt].dat) zag(rt);
        }
        PushUp(rt);
    }
    int GetNum(int rt, int x) {
        if(!rt) return -1;
        if(a[a[rt].l].size >= x) return GetNum(a[rt].l, x);
        if(a[a[rt].l].size + 1 >=x) return a[rt].num;
        return GetNum(a[rt].r,x - 1 - a[a[rt].l].size);
    }
    void merge(int /*x*/&x, int &y) {
        if(!y) return;
        if(a[y].l)
        merge(x, a[y].l);
        if(a[y].r)
        merge(x, a[y].r);
        Insert(x, a[y].val, a[y].num);del(y);
    }
}bst;
void merge(int u, int v) {
    int r1 = ufs.find(u), r2 = ufs.find(v);
    if(r1 != r2) {
        if(a[id[r1]].size < a[id[r2]].size) {
            ufs.fa[r1] = r2;
            bst.merge(id[r2], id[r1]);
        }else {
            ufs.fa[r2] = r1;
            bst.merge(id[r1], id[r2]);
        }
    }
}
int main() {
    n = init(); m = init();
    ufs.unit();
    for(int i = 0; i < MAXN; i++) pool[i] = i;
    for(int i = 1; i <= n; i++) {
        int t = init();
        id[i] = bst.New(t, i);
    }
    for(int i = 1; i <= m; i++) {
        int u = init(), v = init();
        if(!u || !v) continue;
        merge(u, v);
    }
    q = init();
    for(int i = 1; i <= q; i++) {
        char t;
        scanf(" %c ", &t);
        if(t == 'Q') {
            int x = init(), k = init();
            printf("%d\n", bst.GetNum(id[ufs.find(x)], k));
        }else {
            int u = init(), v = init();
            if(!u || !v) continue;
            merge(u, v);
        }
    }
    return 0;
}
洛谷 [P3224] 永无乡的更多相关文章
- 洛谷P3224 永无乡 [HNOI2012] 线段树/splay/treap
		正解:线段树合并 解题报告: 传送门! 这题也是有很多解法,eg:splay,treap,... 然而我都不会我会学的QAQ! 反正今天就只讲下线段树合并怎么做QAQ 首先看到这样子的说第k重要的是什 ... 
- 【Luogu】P3224永无乡(splay)
		题目链接 splay模板,启发式合并(其实就是暴力插入)即可. 顺便吐槽时限,带垃圾回收而已……不至于最后一个点死活不让过吧? #include<cstdio> #include<c ... 
- 洛谷 P3224 [HNOI2012]永无乡 解题报告
		P3224 [HNOI2012]永无乡 题目描述 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 ... 
- 洛谷P3224 [HNOI2012]永无乡(线段树合并+并查集)
		题目描述 永无乡包含 nnn 座岛,编号从 111 到 nnn ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 nnn 座岛排名,名次用 111 到 nnn 来表示.某些岛之间由巨大的桥连接, ... 
- 洛谷 P3224 [HNOI2012]永无乡
		题面 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 \(n\) 座岛排名,名次用 \(1\) 到 \(n\) 来表示.某些岛 ... 
- 线段树合并+并查集 || BZOJ 2733: [HNOI2012]永无乡 || Luogu P3224 [HNOI2012]永无乡
		题面:P3224 [HNOI2012]永无乡 题解: 随便写写 代码: #include<cstdio> #include<cstring> #include<iostr ... 
- 【题解】永无乡 [HNOI2012] [BZOJ2733] [P3224]
		[题解]永无乡 [HNOI2012] [BZOJ2733] [P3224] [题目描述] 永无乡包含 \(n\) 座岛,编号从 \(1\) 到 \(n\) ,每座岛都有自己的独一无二的重要度,按照重要 ... 
- P3224 [HNOI2012]永无乡 题解
		P3224 [HNOI2012]永无乡 题解 题意概括 有若干集合,每个集合最初包含一个值,和一个编号1~n.两个操作:合并两个集合,查询包含值x的集合中第k大值最初的集合编号. 思路 维护集合之间关 ... 
- bzoj2733 / P3224 [HNOI2012]永无乡(并查集+线段树合并)
		[HNOI2012]永无乡 每个联通块的点集用动态开点线段树维护 并查集维护图 合并时把线段树也合并就好了. #include<iostream> #include<cstdio&g ... 
随机推荐
- [习题]输入自己的生日(年/月/日)#2 -- 日历(Calendar)控件的时光跳跃,一次跳回五年、十年前?--TodaysDate属性、VisibleDate属性
			原文出處 http://www.dotblogs.com.tw/mis2000lab/archive/2013/06/10/calendar_visibledate_birthday_dropdow ... 
- UIWebView与JavaScript相互调用
			UIWebView与JavaScript的那些事儿 UIWebView是IOS SDK中渲染网面的控件,在显示网页的时候,我们可以hack网页然后显示想显示的内容.其中就要用到javascript的知 ... 
- GRANT - 定义访问权限
			SYNOPSIS GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } [,...] | ALL [ ... 
- 用cssText批量修改样式
			一般情况下我们用js设置元素对象的样式会使用这样的形式: var element= document.getElementById(“id”);element.style.width=”20px”;e ... 
- 行内元素的padding和margin是否无效
			html中元素分为三种:块级元素.行内元素(也叫内联元素),内联块级元素. 常用块级元素:<div>.<p>.<h1>...<h6>.<ol> ... 
- C04 模块化开发
			目录 模块化开发概述 函数概述 如何使用函数 字符串处理函数 模块化开发特点 模块化开发概述 概述 C语言是面向过程的语言,意味着编写C语言程序的时候,我们要像计算机一样思考如何设计程序. 模块化开发 ... 
- 洛谷 P3958 奶酪
			谨以此题来纪念我爆炸的NOIp2017 这个题虽然很多人说是并查集,但是搜索也是毫无压力的,考场搜索细节写挂,爆了个不上不下的80分.今天无意看到这道题,终于AC 首先这道题要考虑一下精度问题,虽然出 ... 
- shell脚本,如何写进度条。
			[root@localhost ~]# cat jindutiao.sh #!/bin/bash #进度条 n=$((/)) N=$((/)) ` do sleep 0.01 [ $(($i%$n)) ... 
- 更新portage之后 安装 certbot
			运行的时候一直报如下的错误: sudo certbot 错误结果: Traceback (most recent call last): File "/usr/lib/python-exec ... 
- 【Git版本控制】Git使用教程
			1.Git的综述 SVN是集中式版本控制系统,版本库集中放在中央服务器上,而干活时用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服务器.集 ... 
