【bzoj2733】 [HNOI2012] 永无乡
2015-11-20 23:43
453 查看
sb题
合并:并查集+线段树启发式合并,注意动态开点
查询:直接查对应线段树的K大。
时间复杂度O(qlog2n)O(q\log^2 n)
合并:并查集+线段树启发式合并,注意动态开点
查询:直接查对应线段树的K大。
时间复杂度O(qlog2n)O(q\log^2 n)
[code]#include <bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a,_=b;i<=_;i++) #define per(i,a,b) for(int i=a,_=b;i>=_;i--) #define maxn 200007 #define maxs 3000007 inline int rd() { char c = getchar(); while (!isdigit(c)) c = getchar() ; int x = c - '0'; while (isdigit(c = getchar())) x = x * 10 + c - '0'; return x; } typedef int arr[maxn]; typedef int seg[maxs]; arr a , h , rt , fa , rk; seg lc , rc , cnt , pool; int s_tot , tot , n , m; inline int newnode() { /*if (s_tot) return pool[s_tot --]; else return ++ tot;*/ return ++ tot; } inline void delnode(int t) { cnt[t] = 0 , lc[t] = rc[t] = 0; pool[s_tot ++] = t; } void _merge(int pr , int&nr) { if (!pr) return; if (!nr) nr = newnode(); cnt[nr] += cnt[pr]; if (cnt[lc[pr]]) _merge(lc[pr] , lc[nr]); if (cnt[rc[pr]]) _merge(rc[pr] , rc[nr]); delnode(pr); } int find(int u) { return u == fa[u] ? u : fa[u] = find(fa[u]); } inline void merge(int u , int v) { u = find(u) , v = find(v); if (u == v) return ; if (rk[u] > rk[v]) swap(u , v); fa[u] = v; if (rk[u] == rk[v]) rk[v] ++; _merge(rt[u] , rt[v]); rt[u] = 0; } void update(int&u , int l , int r , int v) { if (!u) u = newnode(); cnt[u] ++; if (l == r) return ; int m = (l + r) >> 1; if (v <= m) update(lc[u] , l , m , v); else update(rc[u] , m + 1 , r , v); } void input() { n = rd() , m = rd(); rep (i , 1 , n) a[i] = rd(); rep (i , 1 , n) h[a[i]] = i; rep (i , 1 , n) fa[i] = i; rep (i , 1 , n) rk[i] = 1; rep (i , 1 , n) update(rt[i] , 1 , n , a[i]); rep (i , 1 , m) merge(rd() , rd()); } int kth(int u , int l , int r , int k) { int t = 0; if (cnt[u] < k) return -1; while (l < r) { int m = (l + r) >> 1; if (cnt[lc[u]] >= k) u = lc[u] , r = m; else k -= cnt[lc[u]] , u = rc[u] , l = m + 1; } return h[l]; } void query(int u , int k) { u = find(u); int t = kth(rt[u] , 1 , n , k); printf("%d\n" , t); } void solve() { char cmd[2]; rep (q , 1 , rd()) { scanf("%s" , cmd); int u = rd() , v = rd(); if (cmd[0] == 'Q') query(u , v); else merge(u , v); } } int main() { #ifndef ONLINE_JUDGE freopen("data.txt" , "r" , stdin); // freopen("data.out" , "w" , stdout); #endif input(); solve(); return 0; }
相关文章推荐
- Qt查询MYSQL中文乱码问题
- tcp_tw_recycle和tcp_timestamps导致connect失败问题13695
- 群集和ipvs初探(一)
- 关于APP在安卓系统上网络异常的故障分析.
- Linux教程【一】
- 安卓命名规范
- Win10 UWP 开发系列:支持异步的SQLite
- lsof处理df和du大小不一致的问题
- 产品经理入门必读干货 | PMCAFF精选问答整理(不断更新)
- WIFI P2P (WIFI直连)源码解析
- HTML5获取地理位置
- c# 读取txt文件中特定内容后的文字
- HeartBeat+MySQL+DRBD
- 根据输入显示一个人的出生日期(我的第二个python程序)
- 《c语言从入门到精通》看书笔记——第16章 网络套接字编程(下)——套接字
- 安卓任务管理器的设计与实现
- 数据结构作业
- 工作第一天对spring+hibernate+未知框架感悟
- 物联网与嵌入式系统概论-week4-Networking and the Internet-Lesson2: Internet Protocol
- linux下oracle客户端安装