zoukankan      html  css  js  c++  java
  • LUOGU P3391 【模板】文艺平衡树(Splay)

    传送门

    解题思路

      (splay)对于区间的操作,因为(splay)可以任意旋转,比较灵活,所以可以处理区间信息。处理([l,r])时,我们可以把(l-1)这个点转到根,(r+1)这个点转到根的右儿子,那么要处理的区间就是根的右儿子的左子树,然后直接打上标记就行了。然后要插入一个(inf),插入一个(-inf)两个哨兵节点,防止越界。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    
    using namespace std;
    const int MAXN = 100005;
    const int inf = 0x3f3f3f3f;
    
    inline int rd(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
    	while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	return f?x:-x;
    }
    
    int n,m;
    
    struct Splay{
    	int siz[MAXN],ch[MAXN][2],fa[MAXN],val[MAXN],rt,tot,tag[MAXN];
    	inline bool check(int x){
    		return (x==ch[fa[x]][1]);
    	}
    	inline void pushdown(int x){
    		tag[ch[x][0]]^=1;tag[ch[x][1]]^=1;tag[x]=0;
    		swap(ch[x][0],ch[x][1]);
    	}
    	int build(int l,int r,int f){
    		if(l>r) return 0;
    		int now=++tot,mid=(l+r)>>1;fa[now]=f;
    		if(mid==1) val[now]=-inf;else if(mid==n+2) val[now]=inf;
    		else val[now]=mid-1;
    		ch[now][0]=build(l,mid-1,now);ch[now][1]=build(mid+1,r,now);
    		siz[now]=siz[ch[now][0]]+siz[ch[now][1]]+1;
    		return now;
    	}
    	int find(int x){
    		int now=rt;
    		while(1){
    			if(tag[now]) pushdown(now);
    			if(x<=siz[ch[now][0]]) now=ch[now][0];
    			else {
    				x-=siz[ch[now][0]]+1;
    				if(!x) return now;now=ch[now][1];	
    			}
    		}
    	}
    	void rotate(int x){
    		int y=fa[x],z=fa[y];bool chk=check(x);
    		ch[y][chk]=ch[x][chk^1];fa[ch[x][chk^1]]=y;
    		ch[x][chk^1]=y;fa[y]=x;fa[x]=z;if(z) ch[z][(y==ch[z][1])]=x;
    		siz[y]=siz[ch[y][0]]+siz[ch[y][1]]+1;
    		siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    	}
    	void splay(int x,int y){
    		if(tag[x]) pushdown(x);
    		for(int f=fa[x];f!=y;rotate(x),f=fa[x]) 
    			if(fa[f]!=y) rotate(check(x)==check(f)?f:x);
    		if(!y) rt=x;
    	}
    	void reverse(int x,int y){
    		int l=x-1,r=y+1;
    		l=find(l);r=find(r);
    		splay(l,0);splay(r,l);
    		int now=ch[rt][1];now=ch[now][0];
    		tag[now]^=1;
    	}
    	void dfs(int x){
    		if(tag[x]) pushdown(x);
    		if(ch[x][0]) dfs(ch[x][0]);
    		if(val[x]!=inf && val[x]!=-inf) 
    			printf("%d ",val[x]);
    		if(ch[x][1]) dfs(ch[x][1]);
    	}
    }tree;
    
    int main(){
    	n=rd(),m=rd();int l,r;
    	tree.rt=tree.build(1,n+2,0);
    	while(m--){
    		l=rd(),r=rd();
    		tree.reverse(l+1,r+1);
    	}
    	tree.dfs(tree.rt);
    	return 0;
    }
    
  • 相关阅读:
    JVM中java类的加载时机(转载:http://blog.csdn.net/chenleixing/article/details/47099725)
    自定义filter包
    Tomcat中Listener的使用范例(转载http://cywhoyi.iteye.com/blog/2075848)
    Quartz简单使用
    PAT A1119 Pre- and Post-order Traversals [前序后序求中序]
    PAT A1115 Counting Nodes in a BST [二叉搜索树]
    PAT A1110 Complete Binary Tree [完全二叉树]
    PAT A1102 Invert a Binary Tree [反转二叉树]
    PAT A1099 Build A Binary Search Tree [二叉搜索树]
    PAT A1094 The Largest Generation [树的遍历]
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9990427.html
Copyright © 2011-2022 走看看