• Splay维护序列 & 洛谷 P3391 【模板】文艺平衡树


    传送门


    解题思路

    Splay如何维护序列呢?
    以序列下标作为val值,扔到Splay中。
    因为有区间翻转操作,所以实际上并不能保证绝对的按照val值排序,也就是说Splay的中序遍历结果是真正的序列,而val值对应的是当前序列的每个元素原来的位置。

    与普通的Splay的区别在于多了一个区间翻转操作,可以把当前第l-1个元素旋转到根,第r+1个元素旋转到根的右儿子,这样l~r的元素就是以根的右儿子的左儿子为根的子树了,打个lazy tag即可。记得各个操作到达某个节点是先pushdown一下。

    AC代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<bitset>
    #include<stack>
    using namespace std;
    template<class T>inline void read(T &x)
    {
        x=0; char c=getchar(); bool f=0;
        while(!isdigit(c))f^=c=='-',c=getchar();
        while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
        if(f)x=-x;
    }
    template<class T>inline void print(T x)
    {
        if(x<0)putchar('-'),x=-x;
        if(x>9)print(x/10);
        putchar('0'+x%10);
    }
    const int maxn=100005;
    int n,m,cnt,lazy[maxn],rt;
    struct node{
    	int fa,val,son[2],siz;
    }tr[maxn];
    int New(int val,int fa){
    	cnt++;
    	tr[cnt].val=val;
    	tr[cnt].fa=fa;
    	tr[cnt].son[0]=tr[cnt].son[1]=0;
    	tr[cnt].siz=1;
    	return cnt;
    }
    void update(int x){
    	if(!x) return;
    	tr[x].siz=1;
    	if(tr[x].son[0]) tr[x].siz+=tr[tr[x].son[0]].siz;
    	if(tr[x].son[1]) tr[x].siz+=tr[tr[x].son[1]].siz;
    }
    void pushdown(int x){
    	if(lazy[x]){
    		if(tr[x].son[0]) lazy[tr[x].son[0]]^=1;
    		if(tr[x].son[1]) lazy[tr[x].son[1]]^=1;
    		swap(tr[x].son[0],tr[x].son[1]);
    		lazy[x]=0;
    	}
    }
    void rotate(int x){
    	int y=tr[x].fa,z=tr[y].fa;
    	pushdown(y);pushdown(x);
    	int c=(tr[y].son[1]==x);
    	tr[x].fa=z;
    	tr[y].fa=x;
    	if(tr[x].son[!c]) tr[tr[x].son[!c]].fa=y;
    	tr[y].son[c]=tr[x].son[!c];
    	tr[x].son[!c]=y;
    	if(z) tr[z].son[tr[z].son[1]==y]=x;
    	update(y);
    	update(x);
    }
    void splay(int x,int goal){
    	if(x==goal) return;
    	while(tr[x].fa!=goal){
    		int y=tr[x].fa,z=tr[y].fa;
    		if(z!=goal) ((tr[y].son[1]==x)^(tr[z].son[1]==y))?rotate(x):rotate(y);
    		rotate(x);
    	}
    	if(!goal) rt=x;
    }
    void insert(int val){
    	if(!rt){
    		rt=New(val,0);
    		return;
    	}
    	int x=rt;
    	while(1){
    		pushdown(x);
    		if(tr[x].son[tr[x].val<val]) x=tr[x].son[tr[x].val<val];
    		else{
    			tr[x].son[tr[x].val<val]=New(val,x);
    			update(x);
    			splay(cnt,0);
    			return;
    		}
    	}
    }
    
    int find(int tot){
    	int x=rt;
    	while(1){
    		pushdown(x);
    		if(tot>1+(tr[x].son[0]?tr[tr[x].son[0]].siz:0)) tot-=1+(tr[x].son[0]?tr[tr[x].son[0]].siz:0),x=tr[x].son[1];
    		else if(!tr[x].son[0]||tot==1+(tr[x].son[0]?tr[tr[x].son[0]].siz:0)) return x;
    		else x=tr[x].son[0];
    	}
    }
    void Reverse(int l,int r){
    	l=find(l),r=find(r+2);
    	splay(l,0);
    	splay(r,rt);
    	lazy[tr[tr[rt].son[1]].son[0]]^=1;
    }
    int getval(int x){
    	return tr[find(x)].val;
    }
    int main(){
    	read(n);read(m);
    	for(int i=0;i<=n+1;i++) insert(i);
    	for(int i=1;i<=m;i++){
    		int l,r;
    		read(l);read(r);
    		if(l==r) continue;
    		Reverse(l,r);
    	}
    	for(int i=1;i<=n;i++) print(getval(i+1)),putchar(' ');
    	return 0;
    }
    
  • 相关阅读:
    ubuntu下php无法载入mysql扩展
    Ngnix location匹配规则
    Maven 工程错误Failure to transfer org.codehaus.plexus:plexus-io:pom:1.0,Failure to transfer org.codehaus.plexus:plexus-archiver:jar:2.0.1
    把Java Web工程转换为基于Maven的Web工程
    关于"架构"
    CentOS 配置Tomcat服务脚本
    Maven部署web应用到远程服务器
    使用Maven + Jetty时,如何不锁定js css 静态资源
    java final修饰变量时的一种情况
    支付宝快捷支付接入问题
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15518342.html
Copyright © 2020-2023  润新知