• Splay 记录


    luogu 模板 P3391 【模板】文艺平衡树(Splay)。

    知识点:1.splay模板题,练习splay,rotate顺序:x变成z的儿子,x的一个儿子变为y的一个儿子(具体哪个看代码),y变为x的儿子。

        2.splay函数:如起码还需转两次,如最近两次旋转路径为直线,则先转x的父亲,再转x;如为折线,转两次x。

        3.insert函数:记得记录父亲节点,如果父亲存在还要让父亲连向被插入数x,记得新建节点,新建节点两个儿子设置为0,将siz数设为1。

    #include <bits/stdc++.h>
    using namespace std;
    int n,m;
    int cnt = 0;
    struct edge
    {
    	int ch[2];
    	int ff;
    	int siz;
    	int val;
    	int lazy;
    }t[200002];
    int rt = 0;
    void pushup(int x)
    {
    	//错误1:忘记加1(这个点本身),原为t[x].siz = t[t[x].ch[0]].siz + t[t[x].ch[1]].siz; 
    	t[x].siz = t[t[x].ch[0]].siz + t[t[x].ch[1]].siz + 1;
    }
    void pushdown(int x)
    {
        if(t[x].lazy)
        {
            t[t[x].ch[0]].lazy^=1;
            t[t[x].ch[1]].lazy^=1;
            t[x].lazy=0;
            swap(t[x].ch[0],t[x].ch[1]);
        }
    }
    void rotate(int x)
    {
    	int y = t[x].ff;
        int z = t[y].ff;
        int k = t[y].ch[1] == x;
        t[z].ch[t[z].ch[1] == y] = x;
        t[x].ff = z;
        t[y].ch[k] = t[x].ch[k^1];
        t[t[x].ch[k^1]].ff = y;
        t[x].ch[k^1] = y;
        t[y].ff = x;
        pushup(y);
        pushup(x);
    }
    void splay(int x,int goal)
    {
    	while(t[x].ff != goal)
    	{
    		int y = t[x].ff,z = t[y].ff;
    	    if(z != goal)
    	    	if((t[z].ch[1] == y)^(t[y].ch[1] == x))rotate(x);
    	     	else rotate(y);
    	     rotate(x);
    	}
    	if(goal == 0)rt = x;
    }
    void insert(int x)
    {
    	int u = rt,ff = 0;
    	while(u)
    	{
    		ff = u;
    		u = t[u].ch[t[u].val < x];
    	}
        u = ++cnt;
        if(ff)t[ff].ch[t[ff].val < x] = u;
        t[u].val = x;
        t[u].siz = 1;
        t[u].ff = ff;
        t[u].ch[0] = t[u].ch[1] = 0;
        splay(u,0);
    }
    int Kth(int k)
    {
    	int u = rt;
    	while(1)
    	{
    		//错误2:一开始把所有t[t[u].ch[0]].siz写成了t[u].siz,理解错误。 
    		pushdown(u); 
    		if(t[t[u].ch[0]].siz >= k)u = t[u].ch[0];
    		else if(t[t[u].ch[0]].siz + 1 == k)return u;
    		else k -= (t[t[u].ch[0]].siz + 1),u = t[u].ch[1];
    	}
    	
    }
    
    void work(int l,int r)
    {
    	int ls = Kth(l);
    	int rs = Kth(r + 2);
    	splay(ls,0);
    	splay(rs,ls);
    	t[t[t[rt].ch[1]].ch[0]].lazy ^= 1;
    }
    void print(int u)
    {
        pushdown(u);
        if(t[u].ch[0])print(t[u].ch[0]);
        if(t[u].val>1&&t[u].val<n+2)printf("%d ",t[u].val-1);
        if(t[u].ch[1])print(t[u].ch[1]);
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i = 1;i <= n + 2;i++)insert(i);//这里是因为要留出两个空节点,一头一尾,给1当前驱,给n当后继,而1变成2,2变成3.....n变成n + 1。 
    	int l,r;
        while(m--)
        {
        	scanf("%d%d",&l,&r);
        	work(l,r);
        }
        print(rt);
        return 0;
    }

  • 相关阅读:
    Find the Smallest K Elements in an Array
    Count of Smaller Number
    Number of Inversion Couple
    Delete False Elements
    Sort Array
    Tree Diameter
    Segment Tree Implementation
    Java Programming Mock Tests
    zz Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)
    Algorithm about SubArrays & SubStrings
  • 原文地址:https://www.cnblogs.com/xyj1/p/10416264.html
Copyright © 2020-2023  润新知