• P3391 【模板】文艺平衡树


    Splay 区间翻转,存个代码

    旋转时,要注意goal是引用 , 并记得修改 , 有标记的一定记得标记下放 , 还有清空

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N = 101000;
    inline int read()
    {
    	register int x = 0 , f = 0; register char c = getchar();
    	while(c < '0' || c > '9') f |= c == '-' , c = getchar();
    	while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
    	return f ? -x : x;
    }
    #define RQ puts("RQ");
    int n , m , sz , root;
    int tr[N][2] , val[N] , rev[N] , fa[N] , siz[N];
    inline int Newnode() { return ++sz; }
    inline void update(int x) { siz[x] = siz[tr[x][0]] + siz[tr[x][1]] + 1; }
    inline int witch(int x) { return x == tr[fa[x]][1]; }
    inline int rk(int x) { return 1 + siz[tr[x][0]]; }
    void rot(int x , int &goal) // 忘记了修改 goal 
    {
    	int y = fa[x] , z = fa[y] , k = witch(x) , w = tr[x][!k];
    	if(y == goal) goal = x; else tr[z][witch(y)] = x; 
    	fa[x] = z; tr[y][k] = w; if(w) fa[w] = y;
    	tr[x][!k] = y; fa[y] = x;
    	update(y); update(x);
    }
    
    void down(int x)
    {
    	if(!x || !rev[x]) return ; // 没用判断标记 
    	swap(tr[x][0] , tr[x][1]);
    	if(tr[x][0]) rev[tr[x][0]] ^= 1;
    	if(tr[x][1]) rev[tr[x][1]] ^= 1;
    	rev[x] = 0; // 还没有清空 
    	return ;
    }
    
    void Splay(int x , int &goal) // 引用 
    {
    	while(x != goal)
    	{
    		if(fa[x] != goal) rot(witch(x) == witch(fa[x]) ? fa[x] : x , goal);
    		rot(x , goal);
    	}
    	return ;
    }
    
    void build(int &k , int l , int r , int f)
    {
    	if(l > r) return ; int mid = (l + r) >> 1;
    	if(!k) k = Newnode(); siz[k] = 1; fa[k] = f; val[k] = mid;
    	build(tr[k][0] , l , mid - 1 , k);
    	build(tr[k][1] , mid + 1 , r , k);
    	update(k); return ;
    }
    
    int kth(int k) // 求的是第k大的是谁 , 而不是k的排名 
    {
    	int p = root;
    	while(down(p) , rk(p) != k)
    	{
    		if(rk(p) < k) k -= rk(p) , p = tr[p][1];
    		else p = tr[p][0];
    	}
    	Splay(p , root);
    	return p;
    }
    
    void reverse(int l , int r)
    {
    	int x = kth(l) , y = kth(r);
    	Splay(x , root); Splay(y , tr[x][1]);
    	rev[tr[y][0]] ^= 1; return ;
    }
    
    void dfs(int x)
    {
    	if(!x) return ; down(x);
    	dfs(tr[x][0]);
    	if(val[x] >= 1 && val[x] <= n) printf("%d " , val[x]);
    	dfs(tr[x][1]);
    	return ;
    }
    
    int main()
    {
    	n = read(); m = read();
    	build(root , 0 , n+1 , 0);
    	for(int i = 1 ; i <= m ; ++i)
    	{
    		int l = read() , r = read();
    		reverse(l , r + 2);
    	}
    	dfs(root);
    	return 0;
    }
    
  • 相关阅读:
    正式定居博客圆,发些以前在Topcoder上的练习题,对算法和STL有兴趣的朋友可以看下:)
    TopCoder真题讲解之二
    “命名空间“System”中不存在类型或命名空间名称“Linq”(是缺少程序集引用吗?)”
    短信发送
    JavaScript打印和预览等
    .net获取IP地址的几种方法转载
    WinForm中控件与背景透明
    用C#实现C/S模式下软件自动在线升级转
    Microsoft Access 时间函数汇总
    .net 发送Email 单发 群发
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/12159421.html
Copyright © 2020-2023  润新知