• 「学习笔记」替罪羊树


    「学习笔记」替罪羊树

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

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

    模板

    (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
    */
    

    后缀平衡树改天再更啦~

  • 相关阅读:
    深入浅出C#结构体——封装以太网心跳包的结构为例
    视频在线率统计——基于驱动总线设备的领域驱动设计方法落地
    在net Core3.1上基于winform实现依赖注入实例
    类与结构体性能对比测试——以封装网络心跳包为例
    基于Modbus三种CRC16校验方法的性能对比
    Git在公司内部的使用规范
    基于abp框架的数据库种子数据初始化
    VUE中登录密码显示与隐藏的最简设计——基于iview
    abp框架运行——前后端分离(基于VUE)
    基于HTTPS的接口测试——nginx配置SSL
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/10731715.html
Copyright © 2020-2023  润新知