일반 밸 런 스 트 리 에서 지속 가능 한 밸 런 스 트 리 까지

172532 단어 알고리즘
일반 밸 런 스 트 리 에서 지속 가능 한 밸 런 스 트 리 까지
  • 일반 밸 런 스 트 리
  • 조작 은 각각
  • x 수 삽입
  • x 수 삭제 (같은 수가 여러 개 있 으 면 한 개 만 삭제 하기 때문에)
  • 조회 x 수의 순위 (순 위 는 현재 수 보다 작은 수의 개수 + 1 로 정의)
  • 조회 순 위 는 x 의 수
  • x 의 전구 (전구 정 의 는 x 보다 작고 최대 수)
  • x 의 후계 (후계 정 의 는 x 보다 크 고 가장 작은 수)
  • Splay 버 전 (특수 데 이 터 를 방지 하기 위해 무 작위 루트 변경 작업 추가)
  • #include
    #include
    #include
    #include
    #include
    #define maxn 100005
    #define lson son[now][0]
    #define rson son[now][1]
    using namespace std;
    set<int> s;
    int n,root,tot;
    int son[maxn][2],fa[maxn],val[maxn],siz[maxn];
    void pushup(int now)
    {
               
    	siz[now]=siz[lson]+siz[rson]+1;
    }
    void rotate(int x,int &k)
    {
               
    	int y=fa[x],z=fa[y],l,r;
    	l=son[y][1]==x;r=l^1;
    	if(y==k) k=x;
    	else {
               if(son[z][0]==y) son[z][0]=x;else son[z][1]=x;}
    	fa[x]=z;fa[y]=x;fa[son[x][r]]=y;
    	son[y][l]=son[x][r];son[x][r]=y;
    	pushup(y);pushup(x);
    }
    void splay(int x,int &k)
    {
               
    	while(x!=k)
    	{
               
    		int y=fa[x],z=fa[y];
    		//cout<
    		if(y!=k)
    		{
               
    			if((son[y][0]==x)^(son[z][0]==y)) rotate(x,k);
    			else rotate(y,k);
    		}
    		rotate(x,k);
    	}
    }
    int cnt;
    void insert(int &now,int v,int last)
    {
               
    	//cnt++;
    	if(!now)
    	{
               
    		now=++tot;
    		s.insert(tot);
    		val[tot]=v;
    		fa[now]=last;
    		splay(tot,root);
    		int temp=rand()%tot+1;
    		if(s.find(temp)!=s.end())
    			splay(temp,root);
    		cnt=0;
    		return;
    	}
    	if(v<=val[now]) insert(lson,v,now);
    	else insert(rson,v,now);
    }
    void del(int v)
    {
               
    	int pos=root;
    	while(val[pos]!=v) pos=son[pos][val[pos]<v]; 	splay(pos,root);
    	
    	s.erase(pos);
    	
    	int now=son[pos][1],flag;
    	if(!now)
    	{
               
    		flag=1;
    		now=son[pos][0];
    		if(!now)
    		{
               
    			fa[pos]=0;
    			val[pos]=0;
    			root=0;
    			return;
    		}
    	}
    	else 
    		flag=0;
    	while(son[now][flag]) now=son[now][flag];
    	
    	
    	int t=root;splay(now,root);
    	son[now][flag]=son[t][flag];fa[son[t][flag]]=now;fa[now]=0;
    	pushup(now);
    }
    int getrank(int v)
    {
               
    	cnt=0;
    	int now=root,ans=0;
    	while(now)
    	{
               
    		cnt++;
    		if(v>val[now]) {
               ans+=siz[lson]+1;now=rson;}
    		else now=lson;
    	}
    	//cerr<
    	return ans+1;
    }
    int find(int v)
    {
               
    	int now=root;
    	while(now)
    	{
               
    		if(siz[lson]+1==v) return val[now];
    		else if(siz[lson]+1>v) now=lson;
    		else v-=(siz[lson]+1),now=rson;
    	}
    	return val[now];
    }
    int suf(int v)
    {
               
    	int now=root,ans;
    	while(now)
    	{
               
    		if(val[now]<v){
               ans=val[now];now=rson;}
    		else now=lson;
    	}
    	return ans;
    }
    int nex(int v)
    {
               
    	int now=root,ans;
    	while(now)
    	{
               
    		if(val[now]<=v) now=rson;
    		else {
               ans=val[now];now=lson;}
    	}
    	return ans;
    }
    int main()
    {
               
    	scanf("%d",&n);
    	while(n--)
    	{
               
    		int op,x;
    		scanf("%d%d",&op,&x);
    		if(op==1) insert(root,x,0);
    		if(op==2) del(x);
    		if(op==3) printf("%d
    "
    ,getrank(x)); if(op==4) printf("%d
    "
    ,find(x)); if(op==5) printf("%d
    "
    ,suf(x)); if(op==6) printf("%d
    "
    ,nex(x)); } }

  • Treap 버 전 (쓰기 좋 음)
  • #include
    #include
    #include
    #define maxn 100005
    #define lson son[now][0]
    #define rson son[now][1]
    #define min(a,b) ((a)
    #define max(a,b) ((a)>(b) ? (a):(b))
    const int inf=2e9+5;
    typedef struct nod
    {
               
    	int first,second;
    } nod;
    int root,tot,sz[maxn];
    int son[maxn][2],val[maxn],k[maxn];
    void pushup(int now)
    {
               
        sz[now]=sz[lson]+sz[rson]+1;
    }
    int merge(int x,int y)
    {
               
        if(!x || !y) return x+y;
        if(k[x]<k[y]) return son[x][1]=merge(son[x][1],y),pushup(x),x;
        else return son[y][0]=merge(x,son[y][0]),pushup(y),y;
    }
    nod split(int now,int v)
    {
               
        if(!now)
        {
               
        	nod temp;
        	temp.first=0;
        	temp.second=0;
        	return temp;
    	}
        nod y;
        if(sz[lson]>=v)
        {
               
            y=split(lson,v);
            lson=y.second;
            pushup(now);
            y.second=now;
        }
        else
        {
               
            y=split(rson,v-sz[lson]-1);
            rson=y.first;
            pushup(now);
            y.first=now;
        }
        return y;
    }
    int find(int v)
    {
               
        nod x=split(root,v-1),y=split(x.second,1);
        int ans=y.first;
        root=merge(merge(x.first,ans),y.second);
        return val[ans];
    }
    int rk(int now,int v)
    {
               
        int minn=inf,maxx=0;
        while(now)
        {
               
            if(val[now]==v) minn=min(minn,maxx+sz[lson]+1);
            if(v>val[now]) maxx+=sz[lson]+1,now=rson;
            else now=lson;
        }
        return minn==inf ? maxx : minn;
    }
    void insert(int v)
    {
               
        int pos=rk(root,v);
        nod x=split(root,pos);
        sz[++tot]=1; val[tot]=v; k[tot]=rand();
        root=merge(merge(x.first,tot),x.second);
    }
    void del(int v)
    {
               
        int pos=rk(root,v);
        nod x=split(root,pos-1),y=split(x.second,1);
        root=merge(x.first,y.second);
    }
    int suc(int v)
    {
               
        int now=root,ans=inf;
        while(now)
        {
               
            if(val[now]>v)
            {
               
                ans=min(ans,val[now]);
                now=lson;
            }
            else
                now=rson;
        }
        return ans;
    }
    int pre(int v)
    {
               
        int now=root,ans=-inf;
        while(now)
        {
               
            if(val[now]<v)
            {
               
                ans=max(ans,val[now]);
                now=rson;
            }
            else
                now=lson;
        }
        return ans;
    }
    int main()
    {
               
        int _;
        scanf("%d",&_);
        while(_--)
        {
               
            int op,x;
            scanf("%d%d",&op,&x);
            if(op==1)
                insert(x);
            if(op==2)
                del(x);
            if(op==3)
                printf("%d
    "
    ,rk(root,x)); if(op==4) printf("%d
    "
    ,find(x)); if(op==5) printf("%d
    "
    ,pre(x)); if(op==6) printf("%d
    "
    ,suc(x)); } return 0; }


  • 문예 평형 수
  • 통합 구간 할당 과 뒤 집 힌 Splay
  • #include
    #include
    #include
    #include
    #include 
    #define inf 1000000000
    #define maxn 1000005
    using namespace std;
    int n,m,root,cnt;
    queue<int>q;
    bool tag[maxn],rev[maxn];
    int fa[maxn],id[maxn],a[maxn],son[maxn][2];
    int sum[maxn],siz[maxn],v[maxn],maxx[maxn],lx[maxn],rx[maxn];
    void pushup(int now)
    {
               
    	int lson=son[now][0],rson=son[now][1];
    	sum[now]=sum[lson]+sum[rson]+v[now];
    	siz[now]=siz[lson]+siz[rson]+1;
    	maxx[now]=max(maxx[lson],maxx[rson]);
    	maxx[now]=max(maxx[now],lx[rson]+v[now]+rx[lson]);
    	lx[now]=max(lx[lson],sum[lson]+v[now]+lx[rson]);
    	rx[now]=max(rx[rson],sum[rson]+v[now]+rx[lson]);
    }
    void pushdown(int now)
    {
               
    	int lson=son[now][0],rson=son[now][1];
    	if(tag[now])
    	{
               
    		tag[now]=rev[now]=0;
    		if(lson) tag[lson]=1,v[lson]=v[now],sum[lson]=v[now]*siz[lson];
    		if(rson) tag[rson]=1,v[rson]=v[now],sum[rson]=v[now]*siz[rson];
    		if(v[now]>=0)
    		{
               
    			if(lson) lx[lson]=rx[lson]=maxx[lson]=sum[lson];
    			if(rson) lx[rson]=rx[rson]=maxx[rson]=sum[rson];
    		}
    		else
    		{
               
    			if(lson) lx[lson]=rx[lson]=0,maxx[lson]=v[now];
    			if(rson) lx[rson]=rx[rson]=0,maxx[rson]=v[now];
    		}
    	}
    	if(rev[now])
    	{
               
    		rev[now]^=1;rev[lson]^=1;rev[rson]^=1;
    		swap(lx[lson],rx[lson]);swap(lx[rson],rx[rson]);
    		swap(son[lson][0],son[lson][1]);swap(son[rson][0],son[rson][1]);
    	}
    }
    void rotate(int x,int &k)
    {
               
    	int y=fa[x],z=fa[y],l,r;
    	l=(son[y][1]==x);r=l^1;
    	if(y==k) k=x;
    	else son[z][son[z][1]==y]=x;
    	fa[son[x][r]]=y;fa[y]=x;fa[x]=z;
    	son[y][l]=son[x][r];son[x][r]=y;
    	pushup(y);pushup(x);//        
    }
    void splay(int x,int &k)
    {
               
    	while(x!=k)
    	{
               
    		int y=fa[x],z=fa[y];
    		if(y!=k)
    		{
               
    			if((son[y][0]==x)^(son[z][0]==y)) rotate(x,k);
    			else	rotate(y,k);
    		}
    		rotate(x,k);
    	}
    }
    int find(int now,int rk)
    {
               
    	pushdown(now);
    	int lson=son[now][0],rson=son[now][1];
    	if(siz[lson]+1==rk) return now;
    	if(siz[lson]>=rk) return find(lson,rk);
    	return find(rson,rk-siz[lson]-1);
    }
    void set(int now)
    {
               
    	if(!now) return;
    	int lson=son[now][0],rson=son[now][1];
    	set(lson);set(rson);q.push(now);//     push now 
    	fa[now]=son[now][0]=son[now][1]=0;
    	tag[now]=rev[now]=0;
    	return;
    }
    int split(int now,int tot)
    {
               
    	int x=find(root,now),y=find(root,now+tot+1);
    	splay(x,root);splay(y,son[x][1]);
    	return son[y][0];
    }
    void query(int now,int tot)
    {
               
    	int x=split(now,tot);
    	printf("%d
    "
    ,sum[x]); } void modify(int now,int tot,int val) { int x=split(now,tot),y=fa[x]; tag[x]=1;v[x]=val;sum[x]=val*siz[x]; if(val>=0) lx[x]=rx[x]=maxx[x]=sum[x]; else lx[x]=rx[x]=0,maxx[x]=val; pushup(y);pushup(fa[y]);//pushup } void reverse(int now,int tot) { int x=split(now,tot),y=fa[x]; if(!tag[x]) { rev[x]^=1; swap(son[x][0],son[x][1]); swap(lx[x],rx[x]); pushup(y);pushup(fa[y]); } } void erase(int now,int tot) { int x=split(now,tot),y=fa[x]; set(x);son[y][0]=0; pushup(y);pushup(fa[y]); } void build(int l,int r,int flag) { if(l>r) return; int mid=(l+r)>>1,now=id[mid],last=id[flag]; if(l==r) { sum[now]=a[l]; siz[now]=1; tag[now]=rev[now]=0; if(a[l]>0) lx[now]=rx[now]=maxx[now]=a[l]; else lx[now]=rx[now]=0,maxx[now]=a[l]; } else build(l,mid-1,mid),build(mid+1,r,mid); v[now]=a[mid];fa[now]=last;pushup(now); son[last][mid>=flag]=now; } void insert(int now,int tot) { for(int i=1;i<=tot;i++) scanf("%d",&a[i]); for(int i=1;i<=tot;i++) { if(!q.empty()) id[i]=q.front(),q.pop(); else id[i]=++cnt; } build(1,tot,0); int z=id[(1+tot)>>1]; int x=find(root,now+1),y=find(root,now+2); splay(x,root);splay(y,son[x][1]); fa[z]=y;son[y][0]=z; pushup(y);pushup(x); } void out(int now) { pushdown(now); int lson=son[now][0],rson=son[now][1]; if(lson) out(lson); if(2<=now && now<=n+1) printf("%d ",now-1); if(rson) out(rson); } int main() { scanf("%d%d",&n,&m); maxx[0]=a[1]=a[n+2]=-inf; for(int i=1;i<=n;i++)a[i+1]=i;; for(int i=1;i<=n+2;i++)id[i]=i; build(1,n+2,0); root=(n+3)>>1;cnt=n+2; while(m--) { int l,r; scanf("%d%d",&l,&r); reverse(l,r-l+1); } out(root); }

  • Treap (쉽게 쓰기)
  • #include
    #include
    #include
    #include
    #define maxn 100005
    #define lson (son[now][0])
    #define rson (son[now][1])
    #define mid ((nl+nr)>>1)
    using namespace std;
    int n,m,root;
    int fa[maxn],son[maxn][2],sz[maxn],rev[maxn];
    void pushup(int now)
    {
               
    	sz[now]=sz[lson]+sz[rson]+1;
    }
    void pushdown(int now)
    {
               
    	if(rev[now])
    	{
               
    		swap(lson,rson);
    		rev[lson]^=1; 
    		rev[rson]^=1;
    		rev[now]^=1;
    	}
    }
    void build(int nl,int nr,int pa)
    {
               
    	if(nl>nr) return;
    	if(nl==nr)
    	{
               
    		sz[nl]=1; fa[nl]=pa; son[pa][nl>pa]=nl;
    		return;
    	}
    	build(nl,mid-1,mid);
    	build(mid+1,nr,mid);
    	fa[mid]=pa; son[pa][mid>pa]=mid;
    	pushup(mid);
    }
    void rotate(int x,int &k)
    {
               
    	int y=fa[x],z=fa[y];
    	int l=(son[y][1]==x),r=l^1;
    	if(y==k)
    		k=x;
    	else
    	{
               
    		if(son[z][0]==y) son[z][0]=x;
    		else son[z][1]=x;
    	}
    	fa[x]=z; fa[son[x][r]]=y; fa[y]=x;
    	son[y][l]=son[x][r]; son[x][r]=y;
    	pushup(y); pushup(x);
    }
    void splay(int x,int &k)
    {
               
    	while(x!=k)
    	{
               
    		int y=fa[x],z=fa[y];
    		if(y!=k)
    		{
               
    			int _=0;
    			if((son[z][0]==y) ^_^ (son[y][0]==x))
    				rotate(x,k);
    			else
    				rotate(y,k);
    		}
    		rotate(x,k);
    	}
    }
    int find(int now,int v)
    {
               
    //	cerr<
    	pushdown(now);
    	if(sz[lson]+1==v) return now;
    	if(sz[lson]+1<v) return find(rson,v-(sz[lson]+1));
    	return find(lson,v);
    }
    void reverse(int l,int r)
    {
               
    	l=find(root,l);
    	r=find(root,r+2);
    	splay(l,root);
    	splay(r,son[l][1]);
    	rev[son[r][0]]^=1;
    }
    int main()
    {
               
    	scanf("%d%d",&n,&m);
    	build(1,n+2,0);
    	root=((1+(n+2))>>1);
    	for(int i=1;i<=m;i++)
    	{
               
    		int l,r;
    		scanf("%d%d",&l,&r);
    		reverse(l,r);
    	}
    	for(int i=2;i<=n+1;i++)
    		printf("%d ",find(root,i)-1);
    }
    


  • 밸 런 스 트 리 지속 가능
  • 원래 밸 런 스 트 리 와 다른 점 은 모든 작업 이 특정한 역사 버 전 을 바탕 으로 새로운 버 전 을 만 드 는 것 이다.(조작 3, 4, 5, 6 즉 원판 본 무 변화 유지)
  • 트 립 밖 에 못 써 요.
  • #include
    #include
    #include
    #include
    #include
    #define maxn 500005*60
    #define lson son[now][0]
    #define rson son[now][1]
    using namespace std;
    const int inf=2147483647;
    typedef pair<int,int> pr;
    int root[maxn],tot,sz[maxn],cnt;
    int son[maxn][2],val[maxn],k[maxn];
    void pushup(int now)
    {
               
    	sz[now]=sz[lson]+sz[rson]+1;
    }
    int copy(int now)
    {
               
    	tot++;
    	sz[tot]=sz[now]; son[tot][0]=son[now][0]; son[tot][1]=son[now][1];
    	val[tot]=val[now]; k[tot]=k[now];
    	return tot;
    }
    int merge(int x,int y)
    {
               
    	if(!x || !y) return x+y;
    	if(k[x]<k[y]) return son[x][1]=merge(son[x][1],y),pushup(x),x;
    	else return son[y][0]=merge(x,son[y][0]),pushup(y),y;
    }
    pr split(int now,int v)
    {
               
    	if(!now) return pr(0,0);
    	pr y;
    	if(sz[lson]>=v)
    	{
               
    		int x=copy(now);
    		y=split(lson,v);
    		son[x][0]=y.second;
    		pushup(x);
    		y.second=x;
    	}
    	else
    	{
               
    		int x=copy(now);
    		y=split(rson,v-sz[lson]-1);
    		son[x][1]=y.first;
    		pushup(x);
    		y.first=x;
    	}
    	return y;
    }
    int find(int ver,int v,int p)
    {
               
    	pr x=split(root[ver],v-1),y=split(x.second,1);
    	int ans=y.first;
    	if(p==0)
    	root[ver]=merge(merge(x.first,ans),y.second);
    	else
    	root[++cnt]=merge(merge(x.first,ans),y.second);
    	return val[ans];
    }
    int rk(int now,int v)
    {
               
    	int minn=inf,maxx=0;
    	while(now)
    	{
               
    		if(val[now]==v) minn=min(minn,maxx+sz[lson]+1);
    		if(v>val[now]) maxx+=sz[lson]+1,now=rson;
    		else now=lson;
    	}
    	return minn==inf ? maxx+1 : minn;
    }
    int insrk(int now,int v)
    {
               
    	int minn=inf,maxx=0;
    	while(now)
    	{
               
    		if(val[now]==v) minn=min(minn,maxx+sz[lson]+1);
    		if(v>val[now]) maxx+=sz[lson]+1,now=rson;
    		else now=lson;
    	}
    	return minn==inf ? maxx : minn;
    }
    void insert(int ver,int v)
    {
               
    	int pos=insrk(root[ver],v);
    	pr x=split(root[ver],pos);
    	sz[++tot]=1; val[tot]=v; k[tot]=rand();
    	root[++cnt]=merge(merge(x.first,tot),x.second);
    }
    void del(int ver,int v)
    {
               
    	int pos=rk(root[ver],v);
    	if(find(ver,pos,0)!=v)
    	{
               
    		root[++cnt]=root[ver];
    		return;
    	}
    	pr x=split(root[ver],pos-1),y=split(x.second,1);
    	root[++cnt]=merge(x.first,y.second);
    }
    int suc(int ver,int v)
    {
               
    	int now=root[ver],ans=inf;
    	while(now)
    	{
               
    		if(val[now]>v)
    		{
               
    			ans=min(ans,val[now]);
    			now=lson;
    		}
    		else
    			now=rson;
    	}
    	cnt++;
    	root[cnt]=root[ver];
    	return ans;
    }
    int pre(int ver,int v)
    {
               
    	int now=root[ver],ans=-inf;
    	while(now)
    	{
               
    		if(val[now]<v)
    		{
               
    			ans=max(ans,val[now]);
    			now=rson;
    		}
    		else
    			now=lson;
    	}
    	cnt++;
    	root[cnt]=root[ver];
    	return ans;
    }
    int main()
    {
               
    	int _;
    	scanf("%d",&_);
    	while(_--)
    	{
               
    		int ver,op,x;
    		scanf("%d%d%d",&ver,&op,&x);
    		if(op==1)
    			insert(ver,x);
    		if(op==2)
    			del(ver,x);
    		if(op==3)
    		{
               
    			printf("%d
    "
    ,rk(root[ver],x)); root[++cnt]=root[ver]; } if(op==4) printf("%d
    "
    ,find(ver,x,1)); if(op==5) printf("%d
    "
    ,pre(ver,x)); if(op==6) printf("%d
    "
    ,suc(ver,x)); } }


  • 좋은 웹페이지 즐겨찾기