zoukankan      html  css  js  c++  java
  • 训练计划Day2

    Day2:线段树(可持久化),平衡树(splay,treap),并查集,树链剖分,动态树,树状数组,点分治(可持久)。

    • 线段树模板

    //区间最大,and,or
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    inline void read(int &x){
        x=0;static char ch;static bool flag;flag = false;
        while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
        while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    #define rg register int
    #define rep(i,a,b) for(rg i=(a);i<=(b);++i)
    #define per(i,a,b) for(rg i=(a);i>=(b);++i)
    const int maxn = 100010;
    const int bas = 0x7fffffff;
    int T[maxn<<2],lazy[maxn<<2],sam[maxn<<2];
    int a[maxn];
    inline void update(int rt){
        T[rt] = max(T[rt<<1],T[rt<<1|1]);
        sam[rt] = (sam[rt<<1]&sam[rt<<1|1]) & (~(T[rt<<1]^T[rt<<1|1]));
    }
    inline void pushdown(int rt){
        if(lazy[rt] == 0) return ;
        T[rt<<1] += lazy[rt];lazy[rt<<1] += lazy[rt];
        T[rt<<1|1] += lazy[rt];lazy[rt<<1|1] += lazy[rt];
        lazy[rt] = 0;
    }
    void build(int rt,int l,int r){
        if(l == r){
            T[rt] = a[l];
            sam[rt] = bas;
            return ;
        }int mid = l+r >> 1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        update(rt);
    }
    int L,R,val,tmp;
    inline bool check_a(int rt){
        tmp = (val^bas);
        return (tmp & sam[rt]) == tmp;
    }
    void modify_a(int rt,int l,int r){
        if(L <= l && r <= R && check_a(rt)){
            tmp = (T[rt] & val) - T[rt];
            lazy[rt] += tmp;T[rt] += tmp;
            return ;
        }int mid = l+r >> 1;pushdown(rt);
        if(L <= mid) modify_a(rt<<1,l,mid);
        if(R >  mid) modify_a(rt<<1|1,mid+1,r);
        update(rt);
    }
    void modify_o(int rt,int l,int r){
        if(L <= l && r <= R && (sam[rt] & val) == val){
            tmp = (T[rt] | val) - T[rt];
            lazy[rt] += tmp;T[rt] += tmp;
            return ;
        }int mid = l+r >> 1;pushdown(rt);
        if(L <= mid) modify_o(rt<<1,l,mid);
        if(R >  mid) modify_o(rt<<1|1,mid+1,r);
        update(rt);
    }
    int query(int rt,int l,int r){
        if(L <= l && r <= R) return T[rt];
        int mid = l+r >> 1;pushdown(rt);
        if(R <= mid) return query(rt<<1,l,mid);
        if(L >  mid) return query(rt<<1|1,mid+1,r);
        return max(query(rt<<1,l,mid),query(rt<<1|1,mid+1,r));
    }
    int main(){
        //freopen("series_wei.in","r",stdin);
        //freopen("series_wei.out","w",stdout);
        int n,m;read(n);read(m);
        rep(i,1,n) read(a[i]);
        build(1,1,n);int opt;
        int cnt = 0 ;
        while(m--){
            read(opt);read(L);read(R);
            if(opt == 1) read(val),modify_a(1,1,n);
            else if(opt == 2) read(val),modify_o(1,1,n);
            else printf("%d\n",query(1,1,n));
        }
        return 0;
    }
    
    //poj 3225 线段树成段替换与异或
    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
     
    const int maxn = 131072;
    bool hash[maxn];
    int cover[maxn<<2];
    int XOR[maxn<<2];
    void FXOR(int rt) {
           if (cover[rt] != -1) cover[rt] ^= 1;
           else XOR[rt] ^= 1;
    }
    void PushDown(int rt) {
           if (cover[rt] != -1) {
                  cover[rt<<1] = cover[rt<<1|1] = cover[rt];
                  XOR[rt<<1] = XOR[rt<<1|1] = 0;
                  cover[rt] = -1;
           }
           if (XOR[rt]) {
                  FXOR(rt<<1);
                  FXOR(rt<<1|1);
                  XOR[rt] = 0;
           }
    }
    void update(char op,int L,int R,int l,int r,int rt) {
           if (L <= l && r <= R) {
                  if (op == 'U') {
                         cover[rt] = 1;
                         XOR[rt] = 0;
                  } else if (op == 'D') {
                         cover[rt] = 0;
                         XOR[rt] = 0;
                  } else if (op == 'C' || op == 'S') {
                         FXOR(rt);
                  }
                  return ;
           }
           PushDown(rt);
           int m = (l + r) >> 1;
           if (L <= m) update(op , L , R , lson);
           else if (op == 'I' || op == 'C') {
                  XOR[rt<<1] = cover[rt<<1] = 0;
           }
           if (m < R) update(op , L , R , rson);
           else if (op == 'I' || op == 'C') {
                  XOR[rt<<1|1] = cover[rt<<1|1] = 0;
           }
    }
    void query(int l,int r,int rt) {
           if (cover[rt] == 1) {
                  for (int it = l ; it <= r ; it ++) {
                         hash[it] = true;
                  }
                  return ;
           } else if (cover[rt] == 0) return ;
           if (l == r) return ;
           PushDown(rt);
           int m = (l + r) >> 1;
           query(lson);
           query(rson);
    }
    int main() {
           cover[1] = XOR[1] = 0;
           char op , l , r;
           int a , b;
           while ( ~scanf("%c %c%d,%d%c\n",&op , &l , &a , &b , &r) ) {
                  a <<= 1 , b <<= 1;
                  if (l == '(') a ++;
                  if (r == ')') b --;
                  if (a > b) {
                         if (op == 'C' || op == 'I') {
                                cover[1] = XOR[1] = 0;
                         }
                  } else update(op , a , b , 0 , maxn , 1);
           }
           query(0 , maxn , 1);
           bool flag = false;
           int s = -1 , e;
           for (int i = 0 ; i <= maxn ; i ++) {
                  if (hash[i]) {
                         if (s == -1) s = i;
                         e = i;
                  } else {
                         if (s != -1) {
                                if (flag) printf(" ");
                                flag = true;
                                printf("%c%d,%d%c",s&1?'(':'[' , s>>1 , (e+1)>>1 , e&1?')':']');
                                s = -1;
                         }
                  }
           }
           if (!flag) printf("empty set");
           puts("");
           return 0;
    }
    
    //树状数组扫描线
    #include<vector>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    const int Maxn=4005;
    const int Maxp=1e5+5;
    
    struct node{
        int up,low,v;
    };
    struct node2{
        int p,id;
    };
    int n,m,p,q;
    int ans[Maxp],tr[4*Maxn];
    vector<node> lne[Maxn];
    vector<node2> ask[Maxn];
    
    inline int lowbit(int x){
        return x&(-x);
    }
    inline void read(int &x){
        x=0; int f=1; char ch;
        do{ch=getchar(); if(ch=='-') f=-1;}while(ch<'0'||ch>'9');
        do{x=x*10+ch-'0'; ch=getchar();} while(ch>='0'&&ch<='9');
        x*=f;
    }
    void add(int x,int v){
        for(int i=x;i<=n;i+=lowbit(i))
            tr[i]+=v;
    }
    int srch(int x){
        int sum=0;
        for(int i=x;i;i-=lowbit(i))
            sum+=tr[i];
        return sum;
    }
    int main(){
        read(n),read(m),read(p),read(q);
        for(int i=1;i<=p;i++){
            int a,b,c,d;
            read(a),read(b),read(c),read(d);
            node stp;
            stp.up=a,stp.low=c,stp.v=1;
            lne[b].push_back(stp);
            stp.v=-1;
            lne[d+1].push_back(stp);
        }
        for(int i=1;i<=q;i++){
            int a,b; node2 stp;
            read(a),read(b);
            stp.p=a,stp.id=i;
            ask[b].push_back(stp);
        }
        for(int i=1;i<=m;i++){
            int len=lne[i].size();
            for(int j=0;j<len;j++)
                add(lne[i][j].up   , lne[i][j].v),
                add(lne[i][j].low+1,-lne[i][j].v);
            len=ask[i].size();
            for(int j=0;j<len;j++)
                ans[ask[i][j].id]=srch(ask[i][j].p);
        }
        for(int i=1;i<=q;i++)
            printf("%d\n",ans[i]);
        return 0;
    } 
    
    //可持久线段树k小
    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 3000010;
    
    struct node{
    	int l;
    	int r;
    	int sum;
    }t[maxn<<2];
    
    struct Node{
    	int p;
    	int id;
    }Nod[maxn<<2];
    
    int n;
    int rt[maxn];
    int a[maxn];
    int v[maxn];
    int m;
    int cnt;
    
    inline bool cmp(const Node &x,const Node &y) {
    	return x.p < y.p;
    }
    
    inline void build(int l,int r,int &p,int pos) {
    	++cnt;
    	t[cnt] = t[p];
    	p = cnt;
    	++t[p].sum;
    	if(l == r) return;
    	int mid = (l + r) >> 1;
    	if(pos <= mid) {
    		build(l,mid,t[p].l,pos);
    	}
    	else {
    		build(mid+1,r,t[p].r,pos);
    	}
    	return;
    }
    
    inline int query(int l,int r,int L,int R,int k) {
    	if(l == r) return l;
    	int c = t[t[R].l].sum - t[t[L].l].sum;
    	int mid = (l + r) >> 1;
    	if(c >= k) {
    		return query(l,mid,t[L].l,t[R].l,k);
    	}
    	else {
    		return query(mid +1 ,r,t[L].r,t[R].r,k - c);
    	}
    }
    int l,r,k;
    
    int main (){
    	cin >> n >> m;
    	for(int i = 1;i <= n; ++i) {
    		cin >> Nod[i].p;
    		Nod[i].id = i;		
    	}
    	sort(Nod+1,Nod+n+1,cmp);
    	for(int i = 1;i <= n; ++i) {
    		a[Nod[i].id] = i;
    		v[i] = Nod[i].p;
    	}
    	for(int i = 1;i <= m; ++i) {
    		rt[i] = rt[i - 1];
    		build(1,n,rt[i],a[i]);
    	}
    	while(m--) {
    		cin >> l >> r >> k;
    		cout<<v[query(1,n,rt[l-1],rt[r],k)]<<endl;
    	}
    	return 0;
    }
    
    //可持久线段树历史区间最大,历史单点修改
    #include<cstdio>
    const int maxn=1e4+10;
    const int maxq=1e5+10;
    int n,q,ts,ks;
    int a,b,c,d;
    int tt[maxq];
    struct tree{int s,l,r,mid,lp,rp;}t[maxq<<4];
    inline int min_(int x,int y){return x<y?x:y;}
    inline int max_(int x,int y){return x>y?x:y;}
    void build(int l,int r,int k){
        t[k].l=l,t[k].r=r;
        if(l==r){scanf("%d",&t[k].s);return;}
        t[k].mid=l+r>>1,t[k].lp=++ts,t[k].rp=++ts;
        build(l,t[k].mid,t[k].lp);
        build(t[k].mid+1,r,t[k].rp);
        t[k].s=max_(t[t[k].lp].s,t[t[k].rp].s);
    }
    void change(int k,int nk){
        t[nk].l=t[k].l,t[nk].r=t[k].r;
        if(t[k].l==t[k].r){t[nk].s=d;return;}
        t[nk].mid=t[k].mid;
        if(c<=t[k].mid){
            t[nk].lp=++ts,t[nk].rp=t[k].rp;
            change(t[k].lp,t[nk].lp);
        }
        else{
            t[nk].rp=++ts,t[nk].lp=t[k].lp;
            change(t[k].rp,t[nk].rp);
        }
        t[nk].s=max_(t[t[nk].lp].s,t[t[nk].rp].s);
    }
    int search(int k,int l,int r){
        if(t[k].l==l&&t[k].r==r) return t[k].s;
        int ans=0;
        if(l<=t[k].mid) ans=search(t[k].lp,l,min_(r,t[k].mid));
        if(r>t[k].mid) ans=max_(ans,search(t[k].rp,max_(l,t[k].mid+1),r));
        return ans;
    }
    int main(){
        scanf("%d%d",&n,&q);
        build(1,n,tt[++ks]);
        while(q--){
            scanf("%d%d%d%d",&a,&b,&c,&d);
            if(a){
                tt[++ks]=++ts;
                change(tt[b],tt[ks]);
            }
            else printf("%d\n",search(tt[b],c,d));
        }
        return 0;
    }
    
    //线段树扫描线
    // luogu-judger-enable-o2
    #include<vector>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define getchar() getchar()_locked
    #define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++)
    char BB[1<<15];
    char *S=BB;
    char *T=BB;
    using namespace std;
    const int Maxn=4005;
    const int Maxp=1e5+5;
    
    struct node{
        int up,low,v;
    };
    struct node2{
        int p,id;
    };
    struct node3{
        int l,r,sum,lazy;
    }tr[4*Maxn];
    int ans[Maxp];
    vector<node> lne[Maxn];
    vector<node2> ask[Maxn];
    
    inline void read(int &x){
        x=0; int f=1; char ch;
        do{ch=getchar(); if(ch=='-') f=-1;}while(ch<'0'||ch>'9');
        do{x=x*10+ch-'0'; ch=getchar();} while(ch>='0'&&ch<='9');
        x*=f;
    }
    void build(int p,int x,int y){
        tr[p].l=x,tr[p].r=y,tr[p].sum=0,tr[p].lazy=0;
        if(x==y) return ;
        int mid=(x+y)/2;
        build(p*2,x,mid),build(p*2+1,mid+1,y);
    }
    void push_down(int p){
        if(!tr[p].lazy) return ;
        tr[p * 2].sum+=(tr[p * 2].r-tr[p * 2].l+1)*tr[p].lazy;
        tr[p*2+1].sum+=(tr[p*2+1].r-tr[p*2+1].l+1)*tr[p].lazy;
        tr[p * 2].lazy+=tr[p].lazy;
        tr[p*2+1].lazy+=tr[p].lazy;
        tr[p].lazy=0;
    }
    void add(int p,int x,int y,int v){
        int nl=tr[p].l,nr=tr[p].r;
        if(nl==nr){
            tr[p].sum+=(nr-nl+1)*v;
            tr[p].lazy+=v;
            return ;
        }
        push_down(p);
        int mid=(nl+nr)/2;
        if(y<=mid) add(p*2,x,y,v);
        else if(x>mid) add(p*2+1,x,y,v);
        else add(p*2,x,mid,v),add(p*2+1,mid+1,y,v);
        tr[p].sum=tr[p*2].sum+tr[p*2+1].sum;
        return ;
    }
    int srch(int p,int x){
        int nl=tr[p].l,nr=tr[p].r;
        if(nl==nr)
            return tr[p].sum;
        push_down(p);
        int mid=(nl+nr)/2;
        if(x<=mid) return srch(p*2,x);
        else return srch(p*2+1,x);
    }
    int main(){
        int n,m,p,q; 
        read(n),read(m),read(p),read(q);
        build(1,1,n);
        for(int i=1;i<=p;i++){
            int a,b,c,d;
            read(a),read(b),read(c),read(d);
            node stp;
            stp.up=a,stp.low=c,stp.v=1;
            lne[b].push_back(stp);
            stp.v=-1;
            lne[d+1].push_back(stp);
        }
        for(int i=1;i<=q;i++){
            int a,b; node2 stp;
            read(a),read(b);
            stp.p=a,stp.id=i;
            ask[b].push_back(stp);
        }
        for(int i=1;i<=m;i++){
            int len=lne[i].size();
            for(int j=0;j<len;j++)
                add(1,lne[i][j].up,lne[i][j].low,lne[i][j].v);
            len=ask[i].size();
            for(int j=0;j<len;j++)
                ans[ask[i][j].id]=srch(1,ask[i][j].p);
        }
        for(int i=1;i<=q;i++)
            printf("%d\n",ans[i]);
        return 0;
    } 
    
    //待修改k小
    // luogu-judger-enable-o2
    //bzoj 3065
    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN	700005
    #define MAXV	700005
    #define MAXP	20009999
    #define ALPHA	0.68
    template <typename T> void read(T &x) {
    	x = 0; int f = 1;
    	char c = getchar();
    	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
    	x *= f;
    }
    void getopt(char &c) {
    	c = getchar();
    	while (c != 'Q' && c != 'I' && c != 'M')
    		c = getchar();
    }
    struct Segment_Tree {
    	int now, root[MAXN];
    	int top, mem[MAXP];
    	int lc[MAXP], rc[MAXP], sum[MAXP];
    	void init(int n) {
    		for (int i = 1; i <= n; i++)
    			mem[i] = n - i + 1;
    		top = n;
    	}
    	int new_node() {
    		int tmp = mem[top--];
    		lc[tmp] = rc[tmp] = 0;
    		sum[tmp] = 0;
    		return tmp;
    	}
    	void recycle(int x) {
    		mem[++top] = x;
    	}
    	void dfs(int x) {
    		if (lc[x]) dfs(lc[x]);
    		if (rc[x]) dfs(rc[x]);
    		recycle(x);
    	}
    	void clear(int x) {
    		if (root[x]) dfs(root[x]);
    		root[x] = 0;
    	}
    	void modify(int &root, int l, int r, int pos, int delta) {
    		if (root == 0) root = new_node();
    		sum[root] += delta;
    		if (l == r) return;
    		int mid = (l + r) / 2;
    		if (mid >= pos) modify(lc[root], l, mid, pos, delta);
    		else modify(rc[root], mid + 1, r, pos, delta);
    	}
    	void modify(int x, int v, int d) {
    		modify(root[x], 0, MAXV, v, d);
    	}
    	int query(int k, int len, int *type, int *home) {
    		int l = 0, r = MAXV;
    		for (int i = 1; i <= len; i++)
    			home[i] = root[home[i]];
    		while (l < r) {
    			int mid = (l + r) / 2;
    			int tsum = 0;
    			for (int i = 1; i <= len; i++)
    				tsum += type[i] * sum[lc[home[i]]];
    			if (tsum >= k) {
    				r = mid;
    				for (int i = 1; i <= len; i++)
    					home[i] = lc[home[i]];
    			} else {
    				l = mid + 1;
    				k -= tsum;
    				for (int i = 1; i <= len; i++)
    					home[i] = rc[home[i]];
    			}
    		}
    		return l;
    	}
    } SMT;
    struct Scapegoat_Tree {
    	int root, reroot;
    	int len, tindex[MAXN];
    	int type[MAXN], home[MAXN];
    	int top, mem[MAXN];
    	int lc[MAXN], rc[MAXN];
    	int index[MAXN], size[MAXN];
    	void init(int n) {
    		for (int i = 1; i <= n; i++)
    			mem[i] = n - i + 1;
    		top = n;
    	}
    	int new_node() {
    		int tmp = mem[top--];
    		lc[tmp] = rc[tmp] = 0;
    		index[tmp] = 0;
    		size[tmp] = 0;
    		SMT.clear(tmp);
    		return tmp;
    	}
    	void recycle(int x) {
    		mem[++top] = x;
    	}
    	void update(int x) {
    		size[x] = 1;
    		size[x] += size[lc[x]];
    		size[x] += size[rc[x]];
    	}
    	void dfs(int root) {
    		if (root != reroot) recycle(root);
    		if (lc[root]) dfs(lc[root]);
    		tindex[++len] = index[root];
    		if (rc[root]) dfs(rc[root]);
    	}
    	void rebuild(int root, int l, int r) {
    		for (int i = l; i <= r; i++)
    			SMT.modify(root, tindex[i], 1);
    		int mid = (l + r) / 2;
    		index[root] = tindex[mid];
    		if (mid > l) {
    			lc[root] = new_node();
    			rebuild(lc[root], l, mid - 1);
    		}
    		if (mid < r) {
    			rc[root] = new_node();
    			rebuild(rc[root], mid + 1, r);
    		}
    		update(root);
    	}
    	void rebuild(int root) {
    		len = 0;
    		dfs(root);
    		lc[root] = rc[root] = 0;
    		index[root] = size[root] = 0;
    		SMT.clear(root);
    		rebuild(root, 1, len);
    	}
    	void index_init(int n, int *a) {
    		for (int i = 1; i <= n; i++)
    			tindex[i] = a[i];
    		root = new_node();
    		rebuild(root, 1, n);
    	}
    	bool unbalance(int root) {
    		return max(size[lc[root]], size[rc[root]]) > size[root] * ALPHA + 1;
    	}
    	void insert(int &root, int pos, int value) {
    		if (root == 0) {
    			root = new_node();
    			index[root] = value;
    			size[root] = 1;
    			SMT.modify(root, value, 1);
    			return;
    		}
    		SMT.modify(root, value, 1); size[root]++;
    		if (pos <= size[lc[root]] + 1) insert(lc[root], pos, value);
    		else insert(rc[root], pos - size[lc[root]] - 1, value);
    		if (unbalance(root)) reroot = root;
    	}
    	void insert(int pos, int value) {
    		reroot = 0;
    		insert(root, pos, value);
    		if (reroot) rebuild(reroot);
    	}
    	int modify(int root, int pos, int value) { /*Return Value: Old Index*/
    		SMT.modify(root, value, 1);
    		if (pos <= size[lc[root]]) {
    			int tmp = modify(lc[root], pos, value);
    			SMT.modify(root, tmp, -1);
    			return tmp;
    		} else {
    			pos -= size[lc[root]];
    			if (pos == 1) {
    				int tmp = index[root];
    				index[root] = value;
    				SMT.modify(root, tmp, -1);
    				return tmp;
    			}
    			int tmp = modify(rc[root], pos - 1, value);
    			SMT.modify(root, tmp, -1);
    			return tmp;
    		}
    	}
    	void modify(int pos, int value) {
    		modify(root, pos, value);
    	}
    	void getquery(int root, int l, int r, int t) {
    		int mid = size[lc[root]] + 1;
    		if (mid > r) getquery(lc[root], l, r, t);
    		else if (mid < l) getquery(rc[root], l - mid, r - mid, t);
    		else {
    			len++; home[len] = root; type[len] = t;
    			if (l != 1) getquery(lc[root], 1, l - 1, -t);
    			if (r != size[root]) getquery(rc[root], r - size[lc[root]], size[root] - size[lc[root]] - 1, -t);
    		}
    	}
    	int query(int l, int r, int k) {
    		len = 0;
    		getquery(root, l, r, 1);
    		return SMT.query(k, len, type, home);
    	}
    } SGT;
    int num[MAXN];
    int main() {
    	SMT.init(MAXP - 1);
    	SGT.init(MAXN - 1);
    	int lastans = 0;
    	int n; read(n);
    	for (int i = 1; i <= n; i++)
    		read(num[i]);
    	SGT.index_init(n, num);
    	int m; read(m);
    	for (int i = 1; i <= m; i++) {
    		char opt; int l, r, v;
    		getopt(opt);
    		if (opt == 'I') {
    			read(l), read(v);
    			l ^= lastans;
    			v ^= lastans;
    			SGT.insert(l, v);
    		}
    		if (opt == 'Q') {
    			read(l), read(r), read(v);
    			l ^= lastans;
    			r ^= lastans;
    			v ^= lastans;
    			printf("%d\n", lastans = SGT.query(l, r, v));
    		}
    		if (opt == 'M') {
    			read(l), read(v);
    			l ^= lastans;
    			v ^= lastans;
    			SGT.modify(l, v);
    		}
    	}
    	return 0;
    } 
    
    • 平衡树

    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    #define N 500005
    using namespace std;
    int inline read()
    {
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
    }
    int ch[N][2],val[N],pri[N],siz[N],sz;
    void update(int x){siz[x]=1+siz[ch[x][0]]+siz[ch[x][1]];}
    int new_node(int v)
    {
    siz[++sz]=1;
    val[sz]=v;
    pri[sz]=rand();
    return sz;
    }
    int merge(int x,int y)
    {
    if (!x || !y) return x+y;
    if (pri[x]<pri[y])
    {
    ch[x][1]=merge(ch[x][1],y);
    update(x);
    return x;
    }
    else
    {
    ch[y][0]=merge(x,ch[y][0]);
    update(y);
    return y;
    }
    }
    void split(int now,int k,int &x,int &y)
    {
    if (!now) x=y=0;
    else
    {
    if (val[now]<=k)
    x=now,split(ch[now][1],k,ch[now][1],y);
    else
    y=now,split(ch[now][0],k,x,ch[now][0]);
    update(now);
    }
    }
    int kth(int now,int k)
    {
    while(1)
    {
    if (k<=siz[ch[now][0]])
    now=ch[now][0];
    else
    if (k==siz[ch[now][0]]+1)
    return now;
    else
    k-=siz[ch[now][0]]+1,now=ch[now][1];
    }
    }
    main()
    {
    srand((unsigned)time(NULL));
    int T,com,x,y,z,a,b,root=0;
    scanf("%d",&T);
    while(T--)
    {
    com=read(),a=read();
    if (com==1)
    {
    split(root,a,x,y);
    root=merge(merge(x,new_node(a)),y);
    }
    else
    if (com==2)
    {
    split(root,a,x,z);
    split(x,a-1,x,y);
    y=merge(ch[y][0],ch[y][1]);
    root=merge(merge(x,y),z);
    }
    else
    if (com==3)
    {
    split(root,a-1,x,y);
    printf("%d\n",siz[x]+1);
    root=merge(x,y);
    }
    else
    if (com==4)
    printf("%d\n",val[kth(root,a)]);
    else
    if (com==5)
    {
    split(root,a-1,x,y);
    printf("%d\n",val[kth(x,siz[x])]);
    root=merge(x,y);
    }
    else
    {
    split(root,a,x,y);
    printf("%d\n",val[kth(y,1)]);
    root=merge(x,y);
    }
    }
    }
    //fhq treap
    
    // luogu-judger-enable-o2
    #include<cstdio>
    #include<iostream>
    #include<ctime>
    #include<algorithm>
    
    using namespace std;
    
    int root,n,a,b,tmp;
    int sz;
    struct treap {
        int sz,tot,w,rnd,ch[2];
        int lc,rc;
    } t[1000500];
    
    void update(int x) {
        t[x].sz=t[t[x].ch[0]].sz+t[t[x].ch[1]].sz+t[x].tot;
    }
    
    void turn(int &x,int k) {
        int y=t[x].ch[k^1];
        t[x].ch[k^1]=t[y].ch[k];
        t[y].ch[k]=x;
        update(x);
        update(y);
        x=y;
    }
    
    void insert(int &x,int w) {
        if(!x) {
            t[++sz].w=w;
            t[sz].rnd=rand();
            t[sz].tot=t[sz].sz=1;
            x=sz;
        } else {
            if(t[x].sz++,t[x].w==w)t[x].tot++;
    
            else if(insert(t[x].ch[tmp=w>t[x].w],w),t[t[x].ch[tmp]].rnd>t[x].rnd) {
                turn(x,tmp^1);
            }
        }
    }
    
    void del(int &x,int w) {
        if(!x)return;
        if(t[x].w==w) {
            if(t[x].tot>1)t[x].tot--,t[x].sz--;
            else {
                if(!(t[x].ch[0]&&t[x].ch[1]))x=t[x].ch[0]|t[x].ch[1];
                else
                    turn(x,tmp=t[t[x].ch[0]].rnd>t[t[x].ch[1]].rnd),t[x].sz--,del(t[x].ch[tmp],w);
            }
        } else t[x].sz--,del(t[x].ch[w>t[x].w],w);
    }
    
    int rank1(int x,int w) {
        if(t[x].w==w)return t[t[x].ch[0]].sz+1;
        if(t[x].w<w)return t[t[x].ch[0]].sz+t[x].tot+rank1(t[x].ch[1],w);
        else return rank1(t[x].ch[0],w);
    }
    
    int kth(int x,int w) {
        if(!x)return 0;
        if(w<=t[t[x].ch[0]].sz)return kth(t[x].ch[0],w);
        else if(w>t[t[x].ch[0]].sz+t[x].tot)return kth(t[x].ch[1],w-t[t[x].ch[0]].sz-t[x].tot);
        else return t[x].w;
    }
    
    int pre(int v) {
        insert(root,v);
        tmp=kth(root,rank1(root,v)-1);
        del(root,v);
        return tmp;
    }
    
    int find(int x,int v) {
        return t[x].w==v?x:find(t[x].ch[t[x].w<v],v);
    }
    
    int sub(int v) {
        insert(root,v);
        tmp=kth(root,rank1(root,v)+t[find(root,v)].tot);
        del(root,v);
        return tmp;
    }
    
    int main() {
    
        scanf("%d",&n);
        for(int i=1; i<=n; i++) {
            scanf("%d%d",&a,&b);
            if(a==1)insert(root,b);
            if(a==2)del(root,b);
            if(a==3)printf("%d\n",rank1(root,b));
            if(a==4)printf("%d\n",kth(root,b));
            if(a==5)printf("%d\n",pre(b));
            if(a==6)printf("%d\n",sub(b));
        }
    }
    //treap
    
    #include<cstdio>
    struct SBT {
        int v, sz, ch[2], cnt;
    } t[300005];
    int n, cnt, root;
    #define Upd(k) {\
        t[k].sz = t[t[k].ch[0]].sz + t[t[k].ch[1]].sz + t[k].cnt;\
    }
    void rot(int &k, bool f) {
        int p = t[k].ch[f]; t[k].ch[f] = t[p].ch[!f]; t[p].ch[!f] = k;
        Upd(k); Upd(p); k = p;
    }
    inline void mt(int &k,bool f)
    {
        if(!k) return;
        if(t[t[k].ch[f^1]].sz < t[t[t[k].ch[f]].ch[f]].sz) rot(k, f);
        else if(t[t[k].ch[f^1]].sz < t[t[t[k].ch[f]].ch[f^1]].sz) { rot(t[k].ch[f], f^1); rot(k, f); }
        else return;
        mt(t[k].ch[f],f);
        mt(k,f);
    }
    void Ins(int &k, int x) {
        if(!k) {k = ++ cnt; t[k].sz = t[k].cnt = 1; t[k].v = x; return; }
        ++ t[k].sz;
        if(t[k].v == x) {++ t[k].cnt; return;}
        Ins(t[k].ch[t[k].v < x], x);
        mt(k, t[k].v < x);
    }
    int Del(int &k, int x) {
        if(!k) return k;
        int tmp;
        if(t[k].v == x) {
            if(t[k].cnt > 1) {-- t[k].cnt; --t[k].sz; return k;}
            else if(!(t[k].ch[0]*t[k].ch[1])) {k = t[k].ch[0]+t[k].ch[1];}
            else { tmp = Del(t[k].ch[0], x+1); t[k].cnt = t[tmp].cnt; t[k].v = t[tmp].v; Upd(k); return k; }
        }
        else if((t[k].v < x && !t[k].ch[1]) || (t[k].v > x && ! t[k].ch[0])) { tmp = k; k = t[k].ch[0]; Upd(k); return tmp; }
        else tmp = Del(t[k].ch[t[k].v < x], x);
        Upd(k); return tmp;
    }
    int Ran(int k,int x) {
        if(k==0)return 0;
        if(t[k].v==x)return t[t[k].ch[0]].sz+1;
        else if(x>t[k].v)
            return t[t[k].ch[0]].sz+t[k].cnt+Ran(t[k].ch[1],x);
        else return Ran(t[k].ch[0],x);
    }
    int Kth(int k,int x) {
        if(k==0)return 0;
        if(x<=t[t[k].ch[0]].sz)
            return Kth(t[k].ch[0],x);
        else if(x>t[t[k].ch[0]].sz+t[k].cnt)
            return Kth(t[k].ch[1],x-t[t[k].ch[0]].sz-t[k].cnt);
        else return t[k].v;
    }
    int ans;
    void pred(int k,int x) {
        if(k==0)return;
        if(t[k].v<x) {
            ans=k;
            pred(t[k].ch[1],x);
        } else pred(t[k].ch[0],x);
    }
    void succ(int k,int x) {
        if(k==0)return;
        if(t[k].v>x) {
            ans=k;
            succ(t[k].ch[0],x);
        } else succ(t[k].ch[1],x);
    }
    char c, f;
    inline void GET(int &n) {
        n = 0; f = 1;
        do {c = getchar(); if(c == '-') f = -1;} while(c > '9' || c < '0');
        while(c >= '0' && c <= '9') {n=n*10+c-'0';c=getchar();}
        n *= f;
    }
    int main() {
        GET(n);
        int opt,x;
        for(int i=1; i<=n; i++) {
            GET(opt); GET(x);
            switch(opt) {
                case 1: Ins(root,x); break;
                case 2: Del(root,x); break;
                case 3: printf("%d\n",Ran(root,x)); break;
                case 4: printf("%d\n",Kth(root,x)); break;
                case 5: ans=0; pred(root,x); printf("%d\n",t[ans].v); break;
                case 6: ans=0; succ(root,x); printf("%d\n",t[ans].v); break;
            }
        }
        return 0;
    }
    //SBT
    
    #include <cstdio>
    #define Maxn 1000000
    using namespace std;
    int f[Maxn];//father
    int ch[Maxn][2];//child ; 0 for left ; 1 for right
    int key[Maxn];//key
    int cnt[Maxn];//value
    int siz[Maxn];//size of subtree
    int sz,root;//size of tree and root
    //clear the ndoe
    void clear(int x)
    {
        ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=siz[x]=0;
    }
    //rightson return 1;left son return 0
    int getson(int x)
    {
        return ch[f[x]][1]==x;
    }
    //update the size
    void update(int x)
    {
        siz[x]=cnt[x];
        if (ch[x][0]) siz[x]+=siz[ch[x][0]];
        if (ch[x][1]) siz[x]+=siz[ch[x][1]];
    }
    //retation
    int rotate(int x)
    {
        int fa=f[x],fafa=f[fa],k=getson(x);
        ch[fa][k]=ch[x][k^1];f[ch[fa][k]]=fa;
        ch[x][k^1]=fa;f[fa]=x;
        f[x]=fafa;
        if (fafa)
            ch[fafa][ch[fafa][1]==fa]=x;
        update(fa);update(x);
    }
    //rotate until x is the root
    void splay(int x)
    {
        for (int fa;fa=f[x];rotate(x))
            if (f[fa])
                rotate(getson(x)==getson(fa) ? fa : x);
        root=x;
    }
    int pre()
    {
        int now=ch[root][0];
        while(ch[now][1])
            now=ch[now][1];
        return now;
    }
    int nex()
    {
        int now=ch[root][1];
        while(ch[now][0])
            now=ch[now][0];
        return now;
    }
    //find x's pos
    int findpos(int v)
    {
        int now=root,ans=0;
        while(1)
        {
            if (v<key[now])
                now=ch[now][0];
            else
            {
                ans+=ch[now][0]?siz[ch[now][0]]:0;
                if (v==key[now]) 
                {
                    splay(now);
                    return ans+1;
                }
                ans+=cnt[now];
                now=ch[now][1];
            }
        }
    }
    //find pos's x
    int findx(int x)
    {
        int now=root;
        while(1)
        {
            if (ch[now][0] && x<=siz[ch[now][0]])
                now=ch[now][0];
            else
            {
                int temp=(ch[now][0]?siz[ch[now][0]]:0)+cnt[now];
                if (x<=temp)
                    return key[now];
                x-=temp;
                now=ch[now][1];
            }
        }
    }
    //ceate a new splay node
    void create(int v)
    {
        sz++;
        ch[sz][0]=ch[sz][1]=f[sz]=0;
        key[sz]=v;
        cnt[sz]=1;
        siz[sz]=1;
        //root=sz;
    }
    //insert a node
    void insert(int v)
    {
        if (!root)
            create(v),root=sz;
        else
        {
            int now=root,fa=0;
            while(1)
            {
                if (key[now]==v)
                {
                    cnt[now]++;
                    update(now);update(fa);
                    splay(now);
                    break;
                }
                fa=now;
                now=ch[fa][v>key[fa]];
                if (!now)
                {
                    create(v);
                    f[sz]=fa;
                    ch[fa][v>key[fa]]=sz;
                    update(fa);
                    splay(sz);
                    break;
                }
            }
        }
    }
    void del(int x)
    {
        int t=findpos(x);
        if (cnt[root]>1) 
        {
            cnt[root]--;
            update(root);
            return;
        }
        //none
        if (!ch[root][0] && !ch[root][1])
        {
            clear(root);
            root=0;
            return;
        }
        //one
        if (!ch[root][1])
        {
            int temp=root;
            root=ch[root][0];
            f[root]=0;
            clear(temp);
            return;
        }
        else
        if (!ch[root][0])
        {
            int temp=root;
            root=ch[root][1];
            f[root]=0;
            clear(temp);
            return;
        }
        //two
        int pre1=pre(),temp=root;
        splay(pre1);
        f[ch[temp][1]]=root;
        ch[root][1]=ch[temp][1];
        clear(temp);
        update(root);
    }
    int main()
    {  
        int n,opt,x;  
        scanf("%d",&n);  
        for (int i=1;i<=n;++i)
        {  
            scanf("%d%d",&opt,&x);  
            switch(opt)
            {  
                case 1: insert(x); break;  
                case 2: del(x); break;  
                case 3: printf("%d\n",findpos(x)); break;  
                case 4: printf("%d\n",findx(x)); break;  
                case 5: insert(x); printf("%d\n",key[pre()]); del(x); break;
                case 6: insert(x); printf("%d\n",key[nex()]); del(x); break;
            }  
        }  
    }
    //splay
    
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const double r=0.78;
    const int maxn=100010,oo=0x3f3f3f3f;
    int rd()
    {
        int x=0,f=1;
        char c=getchar();
        while (c<'0'||c>'9')
        {
            if (c=='-') f=-1;
            c=getchar();
        }
        while (c>='0'&&c<='9')
        {
            x=x*10+c-'0';
            c=getchar();
        }
        return x*f;
    }
    int son[maxn][2],siz[maxn],num[maxn],w[maxn],cnt[maxn],
    fid[maxn],fw[maxn],fcnt[maxn],sta[maxn],
    tot,clo,rt,id,fa,b;
    void pause()
    {
        int x;
        x=1;
    }
    void upd(int u)
    {
        if (!u) return;
        siz[u]=siz[son[u][0]]+siz[son[u][1]]+1;
        num[u]=num[son[u][0]]+num[son[u][1]]+cnt[u];
    }
    void check(int u)
    {
        if (!u) return;
        if (siz[son[u][0]]>siz[u]*r||siz[son[u][1]]>siz[u]*r)
            id=u,fa=-1;
        if (son[u][0]==id)
        {
            fa=u;
            b=0;
        }
        if (son[u][1]==id)
        {
            fa=u;
            b=1;
        }
    }
    void dfs(int u)
    {
        if (!u) return;
        dfs(son[u][0]);
        clo++;
        fid[clo]=u;
        fw[clo]=w[u];
        fcnt[clo]=cnt[u];
        dfs(son[u][1]);
    }
    int build(int L,int R)
    {
        if (L>R) return 0;
        int mid=L+R>>1,u;
        u=fid[mid];
        w[u]=fw[mid];
        cnt[u]=fcnt[mid];
        son[u][0]=build(L,mid-1);
        son[u][1]=build(mid+1,R);
        upd(u);
        return u;
    }
    int solve(int u)
    {
        /*if (siz[son[u][0]]==-1) pause();
        printf("%d:%dvs%d\n",siz[u],siz[son[u][0]],siz[son[u][1]]);*/
        clo=0;
        dfs(u);
        return build(1,clo);
    }
    int ins(int u,int x)
    {
        if (!u)
        {
            u=++tot;
            w[u]=x;
            cnt[u]=siz[u]=num[u]=1;
            return u;
        }
        if (w[u]==x)
        {
            cnt[u]++;
            num[u]++;
            return u;
        }
        son[u][x>w[u]]=ins(son[u][x>w[u]],x);
        upd(u);
        check(u);
        return u;
    }
    int del(int u,int x)
    {
        //if (x==-8195776) pause();
        if (x==w[u])
        {
            cnt[u]--;
            if (!cnt[u])
            {
                if (son[u][0]*son[u][1]==0) u=son[u][0]+son[u][1];
                else
                {
                    int fl=siz[son[u][0]]<siz[son[u][1]];
                    int p=son[u][fl],top=0;
                    while (son[p][fl^1]) sta[++top]=p,p=son[p][fl^1];
                    if (top)
                    {
                        son[sta[top]][fl^1]=son[p][fl];
                        son[p][0]=son[u][0];
                        son[p][1]=son[u][1];
                        for (;top;top--) upd(sta[top]);
                    }
                    else son[p][fl^1]=son[u][fl^1];
                    u=p;
                }
            }
            upd(u);
            check(u);
            return u;
        }
        son[u][x>w[u]]=del(son[u][x>w[u]],x);
        upd(u);
        check(u);
        return u;
    }
    int get_rank(int u,int x)
    {
        if (!u) return 0;
        if (x==w[u]) return num[son[u][0]]+1;
        if (x<w[u]) return get_rank(son[u][0],x);
        return cnt[u]+num[son[u][0]]+get_rank(son[u][1],x);
    }
    int qry(int u,int x)
    {
        if (x<=num[son[u][0]]) return qry(son[u][0],x);
        if (x<=cnt[u]+num[son[u][0]]) return w[u];
        return qry(son[u][1],x-(cnt[u]+num[son[u][0]]));
    }
    int pre(int u,int x)
    {
        if (!u) return -oo;
        if (w[u]>=x) return pre(son[u][0],x);
        return max(w[u],pre(son[u][1],x));
    }
    int succ(int u,int x)
    {
        if (!u) return oo;
        if (w[u]<=x) return succ(son[u][1],x);
        return min(w[u],succ(son[u][0],x));
    }
    int main()
    {
        /*freopen("phs.in","r",stdin);
        freopen("phs.out","w",stdout);*/
        int n,opt;
        n=rd();
        while (n--)
        {
            /*if (n%3000==0) printf("%d\n",n);
            if (n%5000==0) pause();*/
            opt=rd();
            switch (opt)
            {
                case 1:
                    id=-1;
                    rt=ins(rt,rd());
                    if (id>0)
                    {
                        if (fa==-1) rt=solve(id);
                        else son[fa][b]=solve(id);
                    }
                    break;
                case 2:
                    id=-1;
                    rt=del(rt,rd());
                    if (id>0)
                    {
                        if (fa==-1) rt=solve(id);
                        else son[fa][b]=solve(id);
                    }
                    break;
                //default:rd();break;
                case 3:printf("%d\n",get_rank(rt,rd()));break;
                case 4:printf("%d\n",qry(rt,rd()));break;
                case 5:printf("%d\n",pre(rt,rd()));break;
                case 6:printf("%d\n",succ(rt,rd()));break;
                /*case 3:get_rank8(rt,rd());break;
                case 4:qry(rt,rd());break;
                case 5:pre(rt,rd());break;
                case 6:succ(rt,rd());break;*/
            }
        }
    }
    //SGT
    
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    using namespace std;
    const int N=5e5+10;
    int n,rt[N],cnt;
    
    struct Node{
        int ch[2];
        int rnd,sz,v;
    }t[N*50];
    
    inline int read()
    {
        int x=0,t=1;
        char ch=getchar();
        while(ch<'0'||ch>'9') {if(ch=='-') t=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*t;
    }
    
    inline int copynode(int x)
    {
        t[++cnt]=t[x];
        return cnt;
    }
    inline int newnode(int x)
    {
       t[++cnt].v=x;t[cnt].sz=1;t[cnt].rnd=rand();
       return cnt;
    }
    inline void update(int k)
    {
        if(k)
        t[k].sz=t[t[k].ch[0]].sz+t[t[k].ch[1]].sz+1;
    }
    
    inline void split(int now,int k,int &x,int &y)
    {
        if(!now) {x=0;y=0;return;}
        if(t[now].v<=k){
            x=copynode(now);
            split(t[x].ch[1],k,t[x].ch[1],y);
        }else{
            y=copynode(now);
            split(t[y].ch[0],k,x,t[y].ch[0]);
        }
        update(x);update(y);
    }
    inline int merge(int x,int y)
    {
        if(!x || !y) return x+y;
        if(t[x].rnd<t[y].rnd){
            int z=copynode(x);
            t[z].ch[1]=merge(t[z].ch[1],y);
            update(z);
            return z;
        }else{
            int z=copynode(y);
            t[z].ch[0]=merge(x,t[z].ch[0]); 
            update(z);
            return z;
        }
    }
    inline void insert(int now,int k)
    {
        int x=0,y=0,z=0;
        split(rt[now],k,x,y);
        z=newnode(k);
        rt[now]=merge(merge(x,z),y);
    }
    
    inline void del(int now,int k)
    {
        int x=0,y=0,z=0;
        split(rt[now],k,x,y);
        split(x,k-1,x,z);
        z=merge(t[z].ch[0],t[z].ch[1]);
        rt[now]=merge(merge(x,z),y);
    }
    
    inline int rnk(int now,int k)
    {
        int x=0,y=0;
        split(rt[now],k-1,x,y);
        return t[x].sz+1;
    }
    
    inline int kth(int x,int k)
    {
       while(1){
          if(t[t[x].ch[0]].sz+1 ==k) return t[x].v;
          else if(t[t[x].ch[0]].sz>=k) x=t[x].ch[0];
          else {k-=(t[t[x].ch[0]].sz+1);x=t[x].ch[1];}
          //1-> cause the same are not on the same
       }
    }
    inline int pre(int now,int k)
    {
       int x=0,y=0,z=0;
       split(rt[now],k-1,x,y);
       if(!x) return -2147483647;
       return kth(x,t[x].sz);
    }
    
    inline int suf(int now,int k)
    {
        int x=0,y=0,z=0;
        split(rt[now],k,x,y);
        if(!y) return 2147483647;
        return kth(y,1);
    }
    
    int main(){
        srand(time(0));
        n=read();
        for(int i=1;i<=n;i++){
            int in=read(),op=read();
            rt[i]=rt[in];
            if(op==1) insert(i,read());
            else 
            if(op==2) del(i,read());
            else 
            if(op==3) printf("%d\n",rnk(i,read()));
            else 
            if(op==4) printf("%d\n",kth(rt[i],read()));
            else 
            if(op==5) printf("%d\n",pre(i,read()));
            else  
            printf("%d\n",suf(i,read()));
        }
        return 0;
    }
    //可持久化平衡树 
    
    • 并查集

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int f[2000010];
    int find(int x)
    {
    	return x==f[x]?x:f[x]=find(f[x]);
    }
    
    void merge(int a,int b){
    	int f1=find(a),f2=find(b);
    	if(f1!=f2){
    		f[f2]=f1;
    	}
    }
    
    int main(){
    	int n,m;
    	cin>>n>>m;
    	for(int i=1;i<=n;i++) f[i]=i;
    	while(m--){
    		int opt;
    		cin>>opt;
    		switch(opt){
    			case(1):{
    				int a,b;
    				cin>>a>>b;
    				merge(a,b);
    				break;
    			}
    			case(2):{
    				int a,b;
    				cin>>a>>b;
    				if(find(a)==find(b)){
    					cout<<"Y"<<endl;
    				}
    				else cout<<"N"<<endl;
    			}
    		}
    	}
    }
    
    #include<cstdio>
    #include<iostream>
    using namespace std;
    inline int read()
    {
        int x=0;char ch=getchar();
        while(ch>'9'||ch<'0')ch=getchar();
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    int n,m,sz,last;
    int root[200005],ls[10000005],rs[10000005],v[10000005],deep[10000005];
    void build(int &k,int l,int r)
    {
        if(!k)k=++sz;
        if(l==r){v[k]=l;return;}
        int mid=(l+r)>>1;
        build(ls[k],l,mid);
        build(rs[k],mid+1,r);
    }
    void modify(int l,int r,int x,int &y,int pos,int val)
    {
        y=++sz;
        if(l==r){v[y]=val;return;}
        ls[y]=ls[x];rs[y]=rs[x];
        int mid=(l+r)>>1;
        if(pos<=mid)
            modify(l,mid,ls[x],ls[y],pos,val);
        else modify(mid+1,r,rs[x],rs[y],pos,val);
    }
    int query(int k,int l,int r,int pos)
    {
        if(l==r)return k;
        int mid=(l+r)>>1;
        if(pos<=mid)return query(ls[k],l,mid,pos);
        else return query(rs[k],mid+1,r,pos);
    }
    void add(int k,int l,int r,int pos)
    {
        if(l==r){deep[k]++;return;}
        int mid=(l+r)>>1;
        if(pos<=mid)add(ls[k],l,mid,pos);
        else add(rs[k],mid+1,r,pos);
    }
    int find(int k,int x)
    {
        int p=query(k,1,n,x);
        if(x==v[p])return p;
        return find(k,v[p]);
    }
    int main()
    {
        n=read();m=read();
        build(root[0],1,n);
        int f,k,a,b;
        for(int i=1;i<=m;i++)
        {
            f=read();
            if(f==1)
            {
                root[i]=root[i-1];
                a=read();b=read();a=a^last;b=b^last;
                int p=find(root[i],a),q=find(root[i],b);
                if(v[p]==v[q])continue;
                if(deep[p]>deep[q])swap(p,q);
                modify(1,n,root[i-1],root[i],v[p],v[q]);
                if(deep[p]==deep[q])add(root[i],1,n,v[q]);
            }
            if(f==2)
            {k=read();k=k^last;root[i]=root[k];}
            if(f==3)
            {
                root[i]=root[i-1];
                a=read();b=read();a=a^last;b=b^last;
                int p=find(root[i],a),q=find(root[i],b);
                if(v[p]==v[q])last=1;
                else last=0;
                printf("%d\n",last);
            }
        }
        return 0;
    }
    //好吧其实可持久并查集和并查集并没什么太大关系,主席树维护持久数组
    
    //留坑二维并查集
    
    • 树链剖分

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    struct tree{int l,r,sum,book;}tr[400005];
    struct edge{int to,nxt;}e[200005];
    int head[100005],tot,cnt;
    int p[100005],y[100005],x[100005],si[100005];
    int dep[100005],fa[100005],bl[100005];
    int n,m,ans,mod,root;
    void add(int u,int v){e[++tot].to=v;e[tot].nxt=head[u];head[u]=tot;}
    void dfs(int u){
        si[u]=1;
        for(int v,c=head[u];c;c=e[c].nxt){
            v=e[c].to;
            if(v==fa[u])continue;
            dep[v]=dep[u]+1;fa[v]=u;
            dfs(v);
            si[u]+=si[v];
        }
    }
    void dfs2(int u,int blo){
        p[u]=++cnt;bl[u]=blo;y[p[u]]=x[u];
        int k=0;
        for(int v,c=head[u];c;c=e[c].nxt){
            v=e[c].to;
            if(dep[v]!=dep[u]+1)continue;
            if(si[v]>si[k])k=v;
        }
        if(k==0)return;
        dfs2(k,blo);
        for(int v,c=head[u];c;c=e[c].nxt){
            if(e[c].to==k)continue;
            v=e[c].to;
            if(dep[v]!=dep[u]+1)continue;
            dfs2(v,v);
        }
    }
    void pushdown(int now){
        tr[now*2].book=(tr[now].book+tr[now*2].book)%mod;
        tr[now*2+1].book=(tr[now].book+tr[now*2+1].book)%mod;
        tr[now].sum=(tr[now].sum+(tr[now].r-tr[now].l+1)*tr[now].book%mod)%mod;
        tr[now].book=0;
    }
    void tr_build(int l,int r,int now){
        tr[now].l=l;tr[now].r=r;
        if(l==r){
            tr[now].sum=y[l];
            return ;
        }
        else{
            int mid=(l+r)/2;
            tr_build(l,mid,now*2);
            tr_build(mid+1,r,now*2+1);
            tr[now].sum=tr[now*2].sum+tr[now*2+1].sum;
        }
    }
    void bt_add(int l,int r,int c,int now){
        if(l==tr[now].l&&r==tr[now].r){
            if(l==r)tr[now].sum=(tr[now].sum+c)%mod;
            else tr[now].book=(tr[now].book+c)%mod;
            return;
        }
        tr[now].sum=(tr[now].sum+(r-l+1)*c%mod)%mod;
        int mid=(tr[now].l+tr[now].r)/2;
        if(l>mid)bt_add(l,r,c,now*2+1);
        else if(r<=mid)bt_add(l,r,c,now*2);
        else{
            bt_add(l,mid,c,now*2);
            bt_add(mid+1,r,c,now*2+1);
        }
    }
    void bt_ser(int l,int r,int now){
        if(l==tr[now].l&&r==tr[now].r){
            ans=(ans+tr[now].sum+(r-l+1)*tr[now].book%mod)%mod;
            return;
        }
        pushdown(now);
        int mid=(tr[now].l+tr[now].r)/2;
        if(l>mid)bt_ser(l,r,now*2+1);
        else if(r<=mid)bt_ser(l,r,now*2);
        else{
            bt_ser(l,mid,now*2);
            bt_ser(mid+1,r,now*2+1);
        }
    }
    void si_add(int u,int v,int s){
        while(bl[u]!=bl[v]){
            if(dep[bl[u]]>dep[bl[v]])swap(u,v);
            bt_add(p[bl[v]],p[v],s,1);
            v=fa[bl[v]];
        }
        if(dep[u]>dep[v])swap(u,v);
        bt_add(p[u],p[v],s,1);
    }
    void si_sum(int u,int v){
        ans=0;
        while(bl[u]!=bl[v]){
            if(dep[bl[u]]>dep[bl[v]])swap(u,v);
            bt_ser(p[bl[v]],p[v],1);
            v=fa[bl[v]];
        }
        if(dep[u]>dep[v])swap(u,v);
        bt_ser(p[u],p[v],1);
        printf("%d\n",ans);
    }
    void tr_add(int u,int s){bt_add(p[u],p[u]+si[u]-1,s,1);}
    void tr_sum(int u){
        ans=0;
        bt_ser(p[u],p[u]+si[u]-1,1);
        printf("%d\n",ans);
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&root,&mod);
        for(int i=1;i<=n;++i)scanf("%d",&x[i]); 
        for(int i=1,u,v;i<n;++i){
            scanf("%d%d",&u,&v);
            add(u,v);add(v,u);
        }
        dfs(root);dfs2(root,root);
        tr_build(1,n,1);
        for(int i=1,opt,u,v,s;i<=m;++i){
            scanf("%d%d",&opt,&u);
            if(opt==1){
                scanf("%d%d",&v,&s);
                si_add(u,v,s%mod);
            }
            else if(opt==2){
                scanf("%d",&v);
                si_sum(u,v);
            }
            else if(opt==3){
                scanf("%d",&s);
                tr_add(u,s%mod);
            }
            else {tr_sum(u);}
        }
        return 0;
    }
    
    • 树状数组

    懒得写了

    • 动态树

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=300005;
    int n,m,top;
    int ch[maxn][2],rev[maxn],que[maxn];
    int fa[maxn],val[maxn],sum[maxn];
    bool isroot(int x){
        return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
    }
    void pushup(int x){
        sum[x]=sum[ch[x][0]]^val[x]^sum[ch[x][1]];
    }
    void pushdown(int x){
        if(rev[x]){
            rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;
            swap(ch[x][0],ch[x][1]);
            rev[x]=0;
        }
    }
    void rotat(int x){
        int y=fa[x],z=fa[y],l,r;
        if(ch[y][0]==x)l=0;else l=1;r=l^1;
        if(!isroot(y)){
            ch[z][ch[z][1]==y]=x;
        }
        fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
        ch[y][l]=ch[x][r];ch[x][r]=y;
        pushup(y);pushup(x);
    }
    void splay(int x){
        int i;
        for(i=x;!isroot(i);i=fa[i]){
            que[++top]=i;
        }
        que[++top]=i;
        while(top)pushdown(que[top--]);
        while(!isroot(x)){
            int y=fa[x],z=fa[y];
            if(!isroot(y)){
                if((ch[z][0]==y)^(ch[y][0]==x))rotat(x);
                else rotat(y);
            }
            rotat(x);
        }
    }
    void access(int x){
        int lst=0;
        while(x){
            splay(x);ch[x][1]=lst;pushup(x);lst=x;x=fa[x];
        }
    }
    void makeroot(int x){
        access(x);splay(x);rev[x]^=1;
    }
    void link(int x,int y){
        makeroot(x);fa[x]=y;pushup(y);
    }
    void cut(int x,int y){
        makeroot(x);access(y);splay(y);
        if(ch[y][0]==x){
            ch[y][0]=fa[x]=0;pushup(y);
        }
    }
    void change(int x,int y){
        access(x);splay(x);val[x]=y;pushup(x);
    }
    int LCT_query(int x,int y){
        makeroot(x);access(y);splay(y);
        return sum[y];
    }
    int findroot(int x){
        access(x);splay(x);
        while(ch[x][0])x=ch[x][0];
        return x;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
            scanf("%d",&val[i]);
        int opt,x,y;
        for(int i=1;i<=m;++i){
            scanf("%d%d%d",&opt,&x,&y);
            switch(opt){
                case 0:{
                    printf("%d\n",LCT_query(x,y));
                    break;
                }
                case 1:{
                    if(findroot(x)!=findroot(y))
                        link(x,y);
                    break;
                }
                case 2:{
                    cut(x,y);
                    break;
                }
                case 3:{
                    change(x,y);
                    break;
                }
            }
        }
        return 0;
    }
    
    • 点分治

    //IOI2011Race
    // luogu-judger-enable-o2
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define maxn 200010
    #define maxk 1000010
    #define INF 1000000009
    struct edge{
        int to,nxt,w;
    }e[maxn<<1];
    int n,root,k,sum,head[maxn],tot,tmp[maxk],dis[maxn],dep[maxn],ans=INF,vis[maxn],siz[maxn],g[maxn];
    void add(int u,int v,int w){
        e[++tot].to=v;
        e[tot].w=w;
        e[tot].nxt=head[u];
        head[u]=tot;
    }
    void getroot(int u,int fa){
        siz[u]=1;
        g[u]=0;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(vis[v]||v==fa) continue;
            getroot(v,u);
            siz[u]+=siz[v];
            g[u]=max(g[u],siz[v]);
        }
        g[u]=max(g[u],sum-siz[u]);
        if(g[u]<g[root]) root=u;
    }
    void dfsdis(int u,int fa){
        if(dis[u]<=k) ans=min(ans,tmp[k-dis[u]]+dep[u]);
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(vis[v]||v==fa) continue;
            dis[v]=dis[u]+e[i].w;
            dep[v]=dep[u]+1;
            dfsdis(v,u);
        }
    }
    void calc(int u,int fa,int p){
        if(dis[u]<=k){
            if(p) tmp[dis[u]]=min(tmp[dis[u]],dep[u]);
            else tmp[dis[u]]=INF;
        }
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(vis[v]||v==fa) continue;
            calc(v,u,p);
        }
    }
    void dfs(int u){
        vis[u]=1; tmp[0]=0;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(vis[v]) continue;
            dis[v]=e[i].w; dep[v]=1;
            dfsdis(v,0);
            calc(v,0,1);
        }
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(vis[v]) continue;
            calc(v,0,0);
        }
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(vis[v]) continue;
            root=0;
            sum=siz[v];
            getroot(v,0);
            dfs(root);
        }
    }
    int main(){
        scanf("%d %d",&n,&k);
        for(int i=1;i<=k;++i) tmp[i]=INF;
        for(int i=1;i<n;++i){
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
            ++u; 
            ++v;
            add(u,v,w); 
            add(v,u,w);
        }
        root=0;
        sum=g[0]=n;
        getroot(1,0);
        dfs(root);
        if(ans!=INF) printf("%d",ans);
        else printf("-1");
        return 0;
    }
    
    点分树比点分治就多一个记录重心父亲
    

    Day2结束,华丽的分割线


  • 相关阅读:
    USB设备驱动之设备初始化(设备枚举)
    clCreateCommandQueue&#39;: was declared deprecated
    Struts2 Result Type
    IOS屏幕旋转
    VMware Workstation 集群仲裁磁盘和数据共享磁盘的创建
    UNIX环境高级编程之第3章:文件I/O
    poj 1068 Parencodings(模拟)
    使用oracle数据库和MySQL数据库时hibernate的映射文件.hbm.xml的不同
    线程池的实现
    zoj 1648 Circuit Board
  • 原文地址:https://www.cnblogs.com/akoasm/p/9419662.html
Copyright © 2011-2022 走看看