【BZOJ】【2733】【HNOI2012】永无乡

平衡树+启发式合并+并查集

  因为要求一坨数中第k大的……用平衡树会很好维护……

  但又要求连通块?所以用并查集来维护……

  大概就是让并查集的fa和Treap的根是同一个节点吧……

TLE了N多发,可能是Treap的随机rank看脸的原因……QAQ

唯一过了的一次是小号……

  1 /**************************************************************
  2     Problem: 2733
  3     User: ProgrammingApe
  4     Language: C++
  5     Result: Accepted
  6     Time:2356 ms
  7     Memory:3640 kb
  8 ****************************************************************/
  9
 10 //BZOJ 2733
 11 #include<cstdio>
 12 #include<cstdlib>
 13 #include<cstring>
 14 #include<iostream>
 15 #include<algorithm>
 16 #define rep(i,n) for(int i=0;i<n;++i)
 17 #define F(i,j,n) for(int i=j;i<=n;++i)
 18 #define D(i,j,n) for(int i=j;i>=n;--i)
 19 using namespace std;
 20
 21 inline int getint(){
 22     int v=0,sign=1; char ch=getchar();
 23     while(ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) sign=-1; ch=getchar();}
 24     while(ch>=‘0‘&&ch<=‘9‘) {v=v*10+ch-‘0‘; ch=getchar();}
 25     return v*=sign;
 26 }
 27 /*******************tamplate********************/
 28 const int N=100010;
 29 struct node{
 30     int ch[2];
 31     int rk,v,size;
 32     node(){}
 33     #define L t[o].ch[0]
 34     #define R t[o].ch[1]
 35 }t[N];
 36 int fa[N],n;
 37 int getfa(int x){ return fa[x]==x ? x : getfa(fa[x]); }
 38 inline void push_up(int o){
 39     t[o].size=t[L].size+t[R].size+1;
 40 }
 41 inline void rotate(int &o,int d){
 42     int k=t[o].ch[!d];
 43     t[o].ch[!d]=t[k].ch[d];
 44     t[k].ch[d]=o;
 45     push_up(o);
 46     o=k;
 47 }
 48 inline void insert(int &o,int x){
 49     if (!o){
 50         o=x; t[o].size=1; L=R=0;
 51         t[o].rk=rand();
 52     }
 53     else{
 54         t[o].size++;
 55         if (t[x].v<t[o].v){
 56             insert(L,x);
 57             if (t[L].rk<t[o].rk) rotate(o,1);
 58         }
 59         else{
 60             insert(R,x);
 61             if (t[R].rk<t[o].rk) rotate(o,0);
 62         }
 63         push_up(o);
 64     }
 65 }
 66 inline void merge(int x,int y){//将x向y合并
 67     if (x==0) return;
 68     merge(t[x].ch[0],y); merge(t[x].ch[1],y);
 69     insert(y,x);
 70 }
 71 inline void solvemerge(){
 72     int x=getint(), y=getint();
 73     int f1=getfa(x),f2=getfa(y);
 74     if (f1==f2) return;
 75     if (t[f1].size>t[f2].size) swap(f1,f2);
 76     fa[f1]=f2;
 77     merge(f1,f2);
 78 }
 79 inline int kth(int o,int k){
 80     while(o){
 81         if (!o || k<=0 || k>t[o].size) return -1;
 82         int s=t[L].size;
 83         if (k==s+1) return o;
 84         else if (k<=s) o=L;
 85         else {o=R; k=k-s-1;}
 86     }
 87     return -1;
 88 }
 89 int main(){
 90     n=getint();
 91     int m=getint(),x,y;
 92     F(i,1,n){
 93         t[i].v=getint();
 94         fa[i]=i; t[i].size=1; t[i].ch[0]=t[i].ch[1]=0;
 95     }
 96     F(i,1,m) solvemerge();
 97     int q=getint();
 98     char cmd[3];
 99     F(i,1,q){
100         scanf("%s",cmd);
101         if (cmd[0]==‘Q‘){
102             x=getint(); y=getint();
103             int f1=getfa(x);
104             printf("%d\n",kth(f1,y));
105         }
106         else solvemerge();
107     }
108     return 0;
109 }

时间: 2024-12-25 09:40:01

【BZOJ】【2733】【HNOI2012】永无乡的相关文章

BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)

不难...treap + 启发式合并 + 并查集 搞搞就行了 ---------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define rep(i, n) for(int i = 0; i &l

Bzoj 2733: [HNOI2012]永无乡 数组Splay+启发式合并

2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3955  Solved: 2112[Submit][Status][Discuss] Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含 0 座)桥可以到达

bzoj 2733: [HNOI2012]永无乡 离线+主席树

2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1167  Solved: 607[Submit][Status] Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a

BZOJ 2733 [HNOI2012]永无乡(启发式合并+Treap+并查集)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2733 [题目大意] 给出n个点,每个点都有自己的重要度,现在有连边操作和查询操作, 查询操作要求找出一个连通块中重要度第k的点的id [题解] 我们用Treap维护每个连通块,对于连边操作,我们用启发式合并, 将size比较小的Treap并入size比较大的Treap,同时用并查集维护连通信息 [代码] #include <cstdio> #include <algorith

bzoj 2733: [HNOI2012]永无乡

23333用并查集维护联通,然后网上搞splay就行啦. %高端splay写法(2333写在struct里了,是不是叫构造函数什么的??) 1 #include<bits/stdc++.h> 2 #define N 100005 3 #define LL long long 4 #define ls tr[x][0] 5 #define rs tr[x][1] 6 using namespace std; 7 inline int ra() 8 { 9 int x=0,f=1; char ch

BZOJ 2733 HNOI2012 永无乡 Treap+启发式合并

题目大意:给定一个无向图以及n个点的排名,多次连接一条边,多次求某个点所在联通块中排名第k小的点的编号 初始对于每个点建立一棵只有一个节点的Treap,然后每次连接两个点,利用并查集找到两个点的根节点,将size较小的Treap暴力拆解插入大的中,然后将小的并查集合并到大的中 今天下午各种脑残,一个小小的Treap改了不下10遍0.0 快去喝脑白金0.0 #include<cstdio> #include<cstring> #include<iostream> #inc

2733: [HNOI2012]永无乡

题解: 爬到了bzoj的数据哈哈哈哈 然后提交上去t了 自己测只有1秒多呀 不理解 然后这题目就是个线段树/平衡树合并裸题 来练一下线段树合并 据说是nlogn的 #include <bits/stdc++.h> using namespace std; const int N=2e5; #define rg register #define IL inline int n,m,fa[N],a[N],b[N],cnt,root[N],count2[N*15],ls[N*15],rs[N*15]

bzoj2733: [HNOI2012]永无乡(splay)

2733: [HNOI2012]永无乡 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3778  Solved: 2020 Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的.现在有两

HNOI2012永无乡

[HNOI2012]永无乡 Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的.现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥.Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x

[BZOJ2733] [HNOI2012] 永无乡 (splay启发式合并)

Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛.如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的.现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥.Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k