zoukankan      html  css  js  c++  java
  • 可持久化平衡树

    可持久化普通平衡树

    题意

    如题。

    解法

    大家都知道,用权值线段树可以过普通平衡树那道题,那么对于可持久化普通平衡树,我们是否也可以用主席树来搞一搞呢。答案是肯定的。只需要动态开点就行了。其他的跟普通平衡树那道题一模一样。

    代码

    这里需要注意一点,当 l 和 r 都是负数的时候, /2 就会有问题,因为 $ -5/2 = -2$ 而 $ -5 >> 1 = -3$ ,所以除2会使 l 一直小于mid,从而陷入死循环。

    #include <bits/stdc++.h>
    #define INF 2147483647
    using namespace std;
    template <typename T>
    inline void read(T &x) {
    	x=0;T k=1;char c=getchar();
    	while(!isdigit(c)) {if(c=='-') k=-1;c=getchar();}
    	while(isdigit(c)) {x=x*10+c-'0';c=getchar();}x*=k;
    }
    
    const int maxn=5e5+5;
    const int ll=-1e9,rr=1e9;
    struct node {
    	int lc,rc,sum;
    }T[maxn*40];
    
    int root[maxn],sz;
    
    void update(int l,int r,int pos,int val,int &x,int y) {
    	T[++sz]=T[y],x=sz;
    	if(l==r) {
    		if(!(T[x].sum==0&&val<0)) T[x].sum+=val;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(pos<=mid) update(l,mid,pos,val,T[x].lc,T[y].lc);
    	else update(mid+1,r,pos,val,T[x].rc,T[y].rc);
    	T[x].sum=T[T[x].lc].sum+T[T[x].rc].sum;
    }
    
    int query(int l,int r,int pos,int x) {
    	if(l==r) return 0;
    	int mid=(l+r)>>1;
    	if(pos<=mid) return query(l,mid,pos,T[x].lc);
    	return T[T[x].lc].sum+query(mid+1,r,pos,T[x].rc);
    }
    
    int kth(int l,int r,int k,int x) {
    	if(l==r) return l;
    	int mid=(l+r)>>1,sum=T[T[x].lc].sum;
    	if(k<=sum) return kth(l,mid,k,T[x].lc);
    	else return kth(mid+1,r,k-sum,T[x].rc);
    }
    
    int pre(int l,int r,int pos,int x) {
    	int k=query(l,r,pos,x);
    	if(k==0) return -INF;
    	else return kth(l,r,k,x);
    }
    
    int query_muilt(int l,int r,int pos,int x) {
    	if(l==r) return T[x].sum;
    	int mid=(l+r)>>1;
    	if(pos<=mid) return query_muilt(l,mid,pos,T[x].lc);
    	else return query_muilt(mid+1,r,pos,T[x].rc);
    }
    
    int nxt(int l,int r,int pos,int x) {
    	int a1=query(l,r,pos,x),a2=query_muilt(l,r,pos,x);
    	if(a1+a2==T[x].sum) return INF;
    	return kth(l,r,a1+a2+1,x);
    }
    
    int n;
    int main() {
    	read(n);
    	for(int i=1;i<=n;i++) {
    		int v,opt,x;
    		read(v),read(opt),read(x);
    		switch(opt) {
    			case 1 : {update(ll,rr,x,1,root[i],root[v]);break;} 
    			case 2 : {update(ll,rr,x,-1,root[i],root[v]);break;} 
    			case 3 : {root[i]=root[v],printf("%d
    ",query(ll,rr,x,root[i])+1);break;} 
    			case 4 : {root[i]=root[v],printf("%d
    ",kth(ll,rr,x,root[i]));break;} 
    			case 5 : {root[i]=root[v],printf("%d
    ",pre(ll,rr,x,root[i]));break;} 
    			case 6 : {root[i]=root[v],printf("%d
    ",nxt(ll,rr,x,root[i]));break;} 
    		}
    	}
    	return 0;
    }
    /*
    10
    0 1 9
    1 1 3
    1 1 10
    2 4 2
    3 3 9
    3 1 2
    6 4 1
    6 2 9
    8 6 3
    4 5 8
    
    */
    
  • 相关阅读:
    对象并不一定都是在堆上分配内存的
    Minor GC、Major GC和Full GC之间的区别
    JAVA内存分配与回收策略
    HotSpot虚拟机对象相关内容
    JAVA运行时数据区域
    Java 的强引用、弱引用、软引用、虚引用
    去哪儿网支付系统架构演进(下篇)
    去哪儿网支付系统架构演进(上)
    心智模式:如何改善我们的心智模式?
    心智模式:心智模式成熟的标志
  • 原文地址:https://www.cnblogs.com/mrasd/p/9532263.html
Copyright © 2011-2022 走看看