zoukankan      html  css  js  c++  java
  • 文艺平衡树(Splay)

    题目背景

    这是一道经典的Splay模板题——文艺平衡树。

    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1

    输入输出格式

    输入格式:

    第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, cdots n-1,n)(1,2,n1,n) m表示翻转操作次数

    接下来m行每行两个数 [l,r][l,r] 数据保证 1 leq l leq r leq n1lrn

    输出格式:

    输出一行n个数字,表示原始序列经过m次变换后的结果

    输入输出样例

    输入样例#1:
    5 3
    1 3
    1 3
    1 4
    输出样例#1:
    4 3 2 1 5

    说明

    n, m leq 100000n,m100000

    splay区间翻转每个区间逐层翻转然后合并

    当然我们并不需要每次翻转就直接翻到底,而是打一个标记,类似于线段树,在查询的时候在随着查询的深入翻转 

    #include<cstdio>
    #include<iostream>
    using namespace std;
    #define N 100005
    int n,m;
    struct node{
        int siz,fa,ch[2];//0zuo,1you;
        bool rev;
    }tr[N];
    int root;
    void push_down(int rt)
    {
        if(tr[rt].rev)
        {
            swap(tr[rt].ch[1],tr[rt].ch[0]);
            tr[rt].rev=0;
            tr[tr[rt].ch[0]].rev^=1;tr[tr[rt].ch[1]].rev^=1;
        }
    }
    void pushup(int rt)
    {
        tr[rt].siz=tr[tr[rt].ch[0]].siz+tr[tr[rt].ch[1]].siz+1;
        return;
    }
    int find(int rt,int x)
    {
        if(rt==0)return 0;
        push_down(rt);
        if(x<=tr[tr[rt].ch[0]].siz)return find(tr[rt].ch[0],x);
        if(x==tr[tr[rt].ch[0]].siz+1)return rt;
        return find(tr[rt].ch[1],x-tr[tr[rt].ch[0]].siz-1);
    }
    void rotate(int &rt,int x)
    {
        int y=tr[x].fa,q=tr[y].fa;
        bool dy=tr[y].ch[1]==x,dz=tr[q].ch[1]==y;
        push_down(y);
        if(rt==y)rt=x,tr[x].fa=q;
        else tr[q].ch[dz]=x,tr[x].fa=q;
        tr[y].ch[dy]=tr[x].ch[dy^1],tr[tr[x].ch[dy^1]].fa=y;
        tr[x].ch[dy^1]=y,tr[y].fa=x;
        pushup(y);
        return ;
    }
    void splay(int &rt,int x)
    {
        push_down(x);
        while(rt!=x)
        {
            int y=tr[x].fa;int q=tr[y].fa;
            if(y!=rt)
            {
                if(tr[y].ch[1]==x^tr[q].ch[1]==y)rotate(rt,x);
                else rotate(rt,y);
            }
            rotate(rt,x);
        }
        pushup(x);
        return;
    }
    void print(int rt)
    {
        if(rt==0)return;
        push_down(rt);
        print(tr[rt].ch[0]);
        if(rt>1&&rt<n+2)printf("%d ",rt-1);
        print(tr[rt].ch[1]);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n+2;i++)
        {
            tr[i].siz=n+3-i;tr[i].fa=i-1;tr[i].ch[1]=i+1;
        }
        tr[n+2].ch[1]=0,root=1;
        while(m--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            splay(root,find(root,l));
            splay(tr[root].ch[1],find(root,r+2));
            tr[tr[tr[root].ch[1]].ch[0]].rev^=1;
        }
        print(root);
        return 0;
    }
  • 相关阅读:
    javascript--setTimeout定时器
    javascript--BOM的onload事件和onunload事件
    JavaScript--文本框中只允许输入数字的操作(其他字符不显示)
    JavaScript--获取页面盒子中鼠标相对于盒子上、左边框的坐标
    javascript--事件对象e的来源、意义、应用及其属性的用法 function(e){}
    javascript--select标签的添加删除功能的使用
    JavaScript--动态添加元素(纯js书写table并删除数据)
    MyBatis快速入门
    《大型网站技术架构》学习笔记-01概述
    FreeMarker快速入门
  • 原文地址:https://www.cnblogs.com/sssy/p/7326704.html
Copyright © 2011-2022 走看看