zoukankan      html  css  js  c++  java
  • 「学习笔记」替罪羊树

    「学习笔记」替罪羊树

    其实早就会了……开一篇占个坑。

    复杂度不会证,具体可见丽洁姐的论文。

    模板

    (Code Below:)

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=100000+10;
    const int inf=0x3f3f3f3f;
    const double alpha=0.75;
    int n,rt,sz,ch[maxn][2],fa[maxn],siz[maxn],val[maxn],sta[maxn],top;
    
    inline bool balance(int x)
    {
        return 1.0*max(siz[ch[x][0]],siz[ch[x][1]])<alpha*siz[x];
    }
    
    inline void recycle(int x)
    {
        if(ch[x][0]) recycle(ch[x][0]);
        sta[++top]=x;
        if(ch[x][1]) recycle(ch[x][1]);
    }
    
    int build(int l,int r)
    {
        int mid=(l+r)>>1,x=sta[mid];
        ch[x][0]=ch[x][1]=0;
        if(l<mid) fa[ch[x][0]=build(l,mid-1)]=x;
        if(mid<r) fa[ch[x][1]=build(mid+1,r)]=x;
        siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
        return x;
    }
    
    inline void rebuild(int x)
    {
        top=0;recycle(x);
        int y=fa[x],k=(ch[y][1]==x),z=build(1,top);
        ch[y][k]=z;fa[z]=y;
        if(x==rt) rt=z;
    }
    
    inline void insert(int v)
    {
        if(!rt){rt=++sz;siz[rt]=1;val[rt]=v;return;}
        int x=rt,y,k;
        while(1)
        {
            siz[x]++;k=(val[x]<=v);y=x;x=ch[x][k];
            if(!x){x=++sz;ch[y][k]=x;fa[x]=y;siz[x]=1;val[x]=v;break;}
        }
        y=0;
        for(;x;x=fa[x])
            if(!balance(x)) y=x;
        if(y) rebuild(y);
    }
    
    inline void erase(int x)
    {
        if(ch[x][0]&&ch[x][1])
        {
            int y=ch[x][0];
            while(ch[y][1]) y=ch[y][1];
            val[x]=val[y];x=y;
        }
        int y=fa[x],k=(ch[y][1]==x),z=ch[x][0]?ch[x][0]:ch[x][1];
        ch[y][k]=z;fa[z]=y;
        for(;y;y=fa[y]) siz[y]--;
        if(x==rt) rt=z;
    }
    
    inline int findid(int v)
    {
        int x=rt,k;
        while(x)
        {
            if(val[x]==v) return x;
            k=(val[x]<=v);x=ch[x][k];
        }
        return -1;
    }
    
    inline int findrnk(int v)
    {
        int x=rt,ans=0;
        while(x)
        {
            if(val[x]>=v) x=ch[x][0];
            else ans+=siz[ch[x][0]]+1,x=ch[x][1];
        }
        return ans+1;
    }
    
    inline int findkth(int k)
    {
        int x=rt;
        while(x)
        {
            if(siz[ch[x][0]]>=k) x=ch[x][0];
            else
            {
                k-=siz[ch[x][0]];
                if(k==1) return val[x];
                k--;x=ch[x][1];
            }
        }
        return -1;
    }
    
    inline int findpre(int v)
    {
        int x=rt,ans=-inf;
        while(x)
        {
            if(val[x]<v) ans=max(ans,val[x]),x=ch[x][1];
            else x=ch[x][0];
        }
        return ans;
    }
    
    inline int findsuc(int v)
    {
        int x=rt,ans=inf;
        while(x)
        {
            if(val[x]>v) ans=min(ans,val[x]),x=ch[x][0];
            else x=ch[x][1];
        }
        return ans;
    }
    
    int main()
    {
        scanf("%d",&n);
        int op,x;
        while(n--)
        {
            scanf("%d%d",&op,&x);
            if(op==1) insert(x);
            if(op==2)
            {
                x=findid(x);
                if(x>0) erase(x);
            }
            if(op==3) printf("%d
    ",findrnk(x));
            if(op==4) printf("%d
    ",findkth(x));
            if(op==5) printf("%d
    ",findpre(x));
            if(op==6) printf("%d
    ",findsuc(x));
        }
        return 0;
    }
    

    没有人的算术

    好题!

    因为 ((x,y)) 最多有 (m) 对,我们考虑用一个平衡树存下所有的二元组,然后 (O(1)) 查询 (rank)

    具体的动态标号可以去看论文中 (O(1)) 查先后关系的算法。

    最大值可以用线段树维护,时间复杂度 (O(nlog n))

    (Code Below:)

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=500000+10;
    const double alpha=0.75;
    int n,m,pos[maxn];double a[maxn];
    
    inline int read()
    {
    	register int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return (f==1)?x:-x;
    }
    
    void print(int x)
    {
    	if(x<0){putchar('-');x=-x;}
    	if(x>9) print(x/10);
    	putchar(x%10+'0');
    }
    
    struct data
    {
    	int l,r;
    	data(int _l=0,int _r=0):l(_l),r(_r){}
    };
    inline bool operator < (const data &x,const data &y)
    {
    	return a[x.l]<a[y.l]||(a[x.l]==a[y.l]&&a[x.r]<a[y.r]);
    }
    inline bool operator == (const data &x,const data &y)
    {
    	return x.l==y.l&&x.r==y.r;
    }
    
    namespace SG
    {
    
    int rt,sz,R,ch[maxn][2],siz[maxn],sta[maxn],top;data val[maxn];
    
    inline bool balance(int x)
    {
    	return 1.0*max(siz[ch[x][0]],siz[ch[x][1]])<alpha*siz[x];
    }
    
    inline void recycle(int x)
    {
    	if(ch[x][0]) recycle(ch[x][0]);
    	sta[++top]=x;
    	if(ch[x][1]) recycle(ch[x][1]);
    }
    
    int build(int l,int r,double _l,double _r)
    {
    	int mid=(l+r)>>1,x=sta[mid];double mv=(_l+_r)/2;
    	ch[x][0]=ch[x][1]=0;a[x]=mv;
    	if(l<mid) ch[x][0]=build(l,mid-1,_l,mv);
    	if(mid<r) ch[x][1]=build(mid+1,r,mv,_r);
    	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    	return x;
    }
    
    inline void rebuild(int &x,double l,double r)
    {
    	top=0;recycle(x);x=build(1,top,l,r);
    }
    
    inline int insert(int &x,double l,double r,data v)
    {
    	double mid=(l+r)/2;int z;
    	if(!x){x=++sz;a[x]=mid;val[x]=v;siz[x]=1;return x;}
    	if(val[x]==v) return x;
    	else
    	{
    		siz[x]++;
    		if(val[x]<v) z=insert(ch[x][1],mid,r,v);
    		else z=insert(ch[x][0],l,mid,v);
    	}
    	if(balance(x))
    	{
    		if(R)
    		{
    			if(ch[x][0]==R) rebuild(ch[x][0],l,mid);
    			else rebuild(ch[x][1],mid,r);
    			R=0;
    		}
    	}
    	else R=x;
    	return z;
    }
    
    }
    
    using SG::rt;
    using SG::R;
    
    namespace ST
    {
    
    #define lson (rt<<1)
    #define rson (rt<<1|1)
    
    int mx[maxn<<2];
    
    inline int cmp(int x,int y)
    {
    	return a[pos[x]]>=a[pos[y]]?x:y;
    }
    
    inline void pushup(int rt)
    {
    	mx[rt]=cmp(mx[lson],mx[rson]);
    }
    
    void build(int l,int r,int rt)
    {
    	if(l == r){mx[rt]=l;return;}
    	int mid=(l+r)>>1;
    	build(l,mid,lson);build(mid+1,r,rson);pushup(rt);
    }
    
    inline void update(int x,int l,int r,int rt)
    {
    	if(l == r){mx[rt]=l;return;}
    	int mid=(l+r)>>1;
    	if(x <= mid) update(x,l,mid,lson);
    	else update(x,mid+1,r,rson);
    	pushup(rt);
    }
    
    int query(int L,int R,int l,int r,int rt)
    {
    	if(L <= l && r <= R) return mx[rt];
    	int mid=(l+r)>>1;
    	if(L > mid) return query(L,R,mid+1,r,rson);
    	if(R <= mid) return query(L,R,l,mid,lson);
    	return cmp(query(L,R,l,mid,lson),query(L,R,mid+1,r,rson));
    }
    
    }
    
    int main()
    {
    	n=read(),m=read();
    	a[0]=-1;SG::insert(rt,0,1,data(0,0));
    	for(int i=1;i<=n;i++) pos[i]=1;
    	ST::build(1,n,1);
    	int l,r,k;char op;
    	while(m--)
    	{
    		op=getchar();
    		while(op!='C'&&op!='Q') op=getchar();
    		l=read(),r=read();
    		if(op=='C')
    		{
    			k=read();
    			pos[k]=SG::insert(rt,0,1,data(pos[l],pos[r]));
    			if(R) SG::rebuild(rt,0,1),R=0;
    			ST::update(k,1,n,1);
    		}
    		else print(ST::query(l,r,1,n,1)),putchar('
    ');
    	}
    	return 0;
    }
    
    /*
    5 10
    C 1 1 1
    C 2 1 2
    Q 1 2
    C 4 4 4
    C 5 5 5
    Q 4 5
    Q 3 3
    C 4 2 3
    C 4 4 4
    Q 3 4
    */
    

    后缀平衡树改天再更啦~

  • 相关阅读:
    入门菜鸟
    FZU 1202
    XMU 1246
    Codeforces 294E Shaass the Great 树形dp
    Codeforces 773D Perishable Roads 最短路 (看题解)
    Codeforces 814E An unavoidable detour for home dp
    Codeforces 567E President and Roads 最短路 + tarjan求桥
    Codeforces 567F Mausoleum dp
    Codeforces 908G New Year and Original Order 数位dp
    Codeforces 813D Two Melodies dp
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/10731715.html
Copyright © 2011-2022 走看看