中级数据结构学习

整理一些板子

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值