整理一些板子
Splay
int newnode(int key,int fa){
++cnt;
T[cnt].key=key;
T[cnt].count=1;
T[cnt].size=1;
T[cnt].son[0]=T[cnt].son[1]=0;
T[cnt].fa=fa;
return cnt;
}
int get(int x){
return(x==T[T[x].fa].son[1]);
}
void clear(int x){
T[x].son[0]=T[x].son[1]=T[x].fa=T[x].count=T[x].key=T[x].size=0;
}
void update(int x){
if(x){
int left=T[x].son[0]?T[T[x].son[0]].size:0;
int right=T[x].son[1]?T[T[x].son[1]].size:0;
T[x].size=left+right+T[x].count;
}
}
void rotate(int x){
int fa=T[x].fa,ga=T[fa].fa,which=get(x);
T[fa].son[which]=T[x].son[!which];
T[T[fa].son[which]].fa=fa;
T[x].son[!which]=fa;
T[fa].fa=x;
T[x].fa=ga;
if(ga){
int d=T[ga].son[1]==fa;
T[ga].son[d]=x;
}
update(fa);
update(x);
}
void splay(int x,int fa)
{
int p=T[x].fa;
for(;p!=fa;rotate(x),p=T[x].fa)
if(T[p].fa!=fa)
rotate(get(x)==get(p)?p:x);
root=x;
if(fa) update(fa);
}
int _insert(int &x,int fa,int key){
if(x==0){
x=newnode(key,fa);
return x;
}else{
if(T[x].key==key){
T[x].count++;
return x;
}
int d=key < T[x].key;
int ret=_insert(T[x].son[!d],x,key);
update(x);
return ret;
}
}
int pre(){
int now=T[root].son[0];
while(T[now].son[1]) now=T[now].son[1];
return now;
}
int next(){
int now=T[root].son[1];
while(T[now].son[0]) now=T[now].son[0];
return now;
}
void insert(int key){
int x=_insert(root,0,key);
splay(x,0);
}
int ffind(int x){
int ans=0,now=root;
while(1){
if(x<T[now].key) now=T[now].son[0];
else{
ans+=T[now].son[0]?T[T[now].son[0]].size :0;
if(x==T[now].key) {
splay(now,0);
return ans+1;
}
ans+=T[now].count;
now=T[now].son[1];
}
}
}
void del(int x){
ffind(x);
if(T[root].count>1){
T[root].count--;
update(root);
return;
}
//Only one point
if(!T[root].son[0]&&!T[root].son[1]){
clear(root);
root=0;
return;
}
//Only one child
if(!T[root].son[0]){
int oldroot=root;
root=T[root].son[1];
T[root].fa=0;
clear(oldroot);
return;
}else if(!T[root].son[1]){
int oldroot=root;
root=T[root].son[0];
T[root].fa=0;
clear(oldroot);
return;
}
//Two children
int leftbig=pre(),oldroot=root;
splay(leftbig,0);
T[T[oldroot].son[1]].fa=root;
T[root].son[1]=T[oldroot].son[1];
clear(oldroot);
update(root);
return;
}
int findx(int x){
int now=root;
while(1){
if(T[now].son[0]&& x<=T[T[now].son[0]].size) now=T[now].son[0];
else{
int temp=(T[now].son[0]?T[T[now].son[0]].size:0) +T[now].count;
if(x<=temp) return T[now].key;
x-=temp;
now=T[now].son[1];
}
}
}
Treap
void maintain(int x){
int left=T[x].son[0]?T[T[x].son[0]].size:0;
int right=T[x].son[1]?T[T[x].son[1]].size:0;
T[x].size=left+right+T[x].count;
}
void rotate(int &x,int p){//case p_0:left,1:right::::x=root
int k=T[x].son[!p];
T[x].son[!p]=T[k].son[p];
T[k].son[p]=x;
T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+T[x].count;
T[k].size=T[T[k].son[0]].size+T[T[k].son[1]].size+T[k].count;
x=k;
}
inline int newnode(int key){
++cnt;
T[cnt].key=key;
T[cnt].pri=rand();
T[cnt].count=1;
T[cnt].size=1;
T[cnt].son[0]=T[cnt].son[1]=0;
return cnt;
}
void insert(int &x,int key){
if(x==0){
x=newnode(key);
}else{
//T[x].size++;
if(T[x].key==key){
T[x].count++;
maintain(x);
return;
}
int d=key < T[x].key;
insert(T[x].son[!d],key);
if(T[x].pri<T[T[x].son[!d]].pri) rotate(x,d);
else maintain(x);
}
}
void del(int &x,int key){
if(x==0) return;
if(T[x].key!=key){
//T[x].size--;
int d=T[x].key>key;
del(T[x].son[!d],key);
}
else if(T[x].count>1){
T[x].count--;
//T[x].size--;
}
else if(T[x].son[0]==0) x=T[x].son[1];
else if(T[x].son[1]==0) x=T[x].son[0];
else{
int d=T[T[x].son[0]].pri>T[T[x].son[1]].pri;
rotate(x,d);
del(T[x].son[d],key);
}
maintain(x);
}
int find(int x,int key,int sum){
if(x==0) return 0;
if(key==T[x].key){
return sum+T[T[x].son[0]].size +1;
}else if(key<T[x].key){
return find(T[x].son[0],key,sum);
}else{
return find(T[x].son[1],key,sum+T[T[x].son[0]].size+T[x].count);
}
}
int rank(int x,int p){
int ret=find(x,p,0);
return ret;
}
int findx(int x,int p){
if(x==0) return 0;
if(T[x].son[0] && (p<(T[T[x].son[0]].size+1))){
return findx(T[x].son[0],p);
}else{
int temp=(T[x].son[0]?T[T[x].son[0]].size:0) + T[x].count;
if(p<=temp){
return T[x].key;
}
return findx(T[x].son[1],p-temp);
}
}
int prev(int rt,int x){
if(rt==0) return 0;
if(x>T[rt].key){
int y=prev(T[rt].son[1],x);
if(y==0||T[rt].key>T[y].key) return rt;
return y;
}else{
return prev(T[rt].son[0],x);
}
}
int next(int rt,int x){
if(rt==0) return 0;
if(x<T[rt].key){
int y=next(T[rt].son[0],x);
if(y==0||T[y].key>T[rt].key) return rt;
return y;
}else{
return next(T[rt].son[1],x);
}
}
主席树
inline int build(int l, int r)
{
int rt = ++ cnt;
sum[rt] = 0;
if (l < r){
L[rt] = build(l, mid);
R[rt] = build(mid+1, r);
}
return rt;
}
inline int update(int pre, int l, int r, int x)
{
int rt = ++ cnt;
L[rt] = L[pre]; R[rt] = R[pre]; sum[rt] = sum[pre]+1;
if (l < r){
if (x <= mid) L[rt] = update(L[pre], l, mid, x);
else R[rt] = update(R[pre], mid+1, r, x);
}
return rt;
}
inline int query(int u, int v, int l, int r, int k)
{
if (l >= r) return l;
int x = sum[L[v]] - sum[L[u]];
if (x >= k) return query(L[u], L[v], l, mid, k);
else return query(R[u], R[v], mid+1, r, k-x);
}
int main()
{
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; i ++){
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(b+1, b+1+n);
m = unique(b+1, b+1+n)-b-1;
T[0] = build(1, m);
for (int i = 1; i <= n; i ++){
int t = lower_bound(b+1, b+1+m, a[i])-b;
T[i] = update(T[i-1], 1, m, t);
}
while (q --){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
int t = query(T[x-1], T[y], 1, m, z);
printf("%d\n", b[t]);
}
return 0;
}
可并堆
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
inline int read() {
int x = 0, flag = 1; char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') flag = -1;
ch = getchar();
}
while(isdigit(ch)) {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * flag;
}
void swap(int &x, int &y) {
int t = x;
x = y;
y = t;
}
const int N = 1e5 + 5;
int ch[N][2], val[N], dis[N], fa[N], n, m;
inline int getfa(int x) {
while(fa[x]) x = fa[x];
return x;
}
inline int merge(int x, int y) {
if(x == 0 || y == 0) return x + y;
if(val[x] > val[y] || (val[x] == val[y] && x > y)) {
swap(x, y);
}
ch[x][1] = merge(ch[x][1], y);
fa[ch[x][1]] = x;
if(dis[ch[x][0]] < dis[ch[x][1]]) {
swap(ch[x][0], ch[x][1]);
}
dis[x] = dis[ch[x][1]] + 1;
return x;
}
inline void pop(int x) {
val[x] = -1;
fa[ch[x][0]] = fa[ch[x][1]] = 0;
merge(ch[x][0], ch[x][1]);
}
int main() {
n = read(); m = read(); dis[0] = -1;
for(int i = 1; i <= n; ++i) val[i] = read();
for(int i = 1; i <= m; ++i) {
int t = read();
if(t == 1) {
int x = read(), y = read();
if(val[x] == -1 || val[y] == -1) continue;
if(x == y) continue;
x =getfa(x); y = getfa(y);
merge(x, y);
} else {
int x = read();
if(val[x] == -1) cout << -1 << endl;
else {
x = getfa(x);
cout << val[x] << endl;
pop(x);
}
}
}
return 0;
}
线段树合并
#include<bits/stdc++.h>
#define N 100005
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int n,m,q,a[N],fa[N*60],siz[N*60],rt[N*60],son[N*60][2],tot=0,mp[N];
inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
inline void update(int&p,int l,int r,int k){
if(!p)p=++tot;
++siz[p];
if(l==r)return;
int mid=l+r>>1;
if(k<=mid)update(son[p][0],l,mid,k);
else update(son[p][1],mid+1,r,k);
}
inline void merge(int&x,int y){
if(!x||!y){x+=y;return;}
siz[x]+=siz[y];
merge(son[x][0],son[y][0]);
merge(son[x][1],son[y][1]);
}
inline int query(int p,int l,int r,int k){
if(l==r)return l;
int mid=l+r>>1;
int tmp=siz[son[p][0]];
if(tmp>=k)return query(son[p][0],l,mid,k);
return query(son[p][1],mid+1,r,k-tmp);
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;++i)a[i]=read(),fa[i]=i,mp[a[i]]=i,update(rt[i],1,n,a[i]);
for(int i=1;i<=m;++i){
int x=read(),y=read();
int fx=find(x),fy=find(y);
if(fx!=fy)fa[fx]=fy,merge(rt[fy],rt[fx]);
}
q=read();
while(q--){
char op[2];
int x,y;
scanf("%s%d%d",op,&x,&y);
if(op[0]=='B'){
int fx=find(x),fy=find(y);
if(fx!=fy){
fa[fx]=fy;
merge(rt[fy],rt[fx]);
}
}
else{
int fx=find(x);
printf("%d\n",siz[rt[fx]]<y?-1:mp[query(rt[fx],1,n,y)]);
}
}
return 0;
}