• P3391 【模板】文艺平衡树(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的模板题。

    splay在解决区间问题的时候是先把l旋转到根节点,再把r旋转到根节点的右孩子,

    然后给根节点的右孩子的左孩子打上标记。

    递归修改即可

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int MAXN=100001;
    inline void read(int &n)
    {	char c='+';int x=0;bool flag=0;
    	while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;}
    	while(c>='0'&&c<='9'){x=x*10+(c-48);c=getchar();}
    	n=flag==1?-x:x;
    }
    struct node
    {
    	int fa,ch[2];// 左右孩子 
    	int size;//大小 
    	bool rev; // 是否需要旋转
    }tree[MAXN];
    int root=0;
    int n,m;
    inline void update(int x)
    {tree[x].size=tree[tree[x].ch[0]].size+tree[tree[x].ch[1]].size+1;}
    inline void connect(int x,int f,bool how)
    {tree[x].fa=f;	tree[tree[x].fa].ch[how]=x;}
    inline void pushdown(int x)
    {
    	if(tree[x].rev)
    		swap(tree[x].ch[0],tree[x].ch[1]),
    		tree[tree[x].ch[0]].rev^=1,tree[tree[x].ch[1]].rev^=1,tree[x].rev=0;
    }
    int build(int l,int r)
    {
    	if(l>r)	return 0;
    	int mid=(l+r)>>1;
    	connect(build(l,mid-1),mid,0);	connect(build(mid+1,r),mid,1);
    	tree[mid].rev=0;
    	update(mid);	return mid;
    }
    inline bool get(int x)
    {
    	return tree[tree[x].fa].ch[1]==x;
    }
    inline int find(int x)
    {
    	--x;int now=root;pushdown(now);
    	while(x!=tree[tree[now].ch[0]].size)
    	{
    		if(tree[tree[now].ch[0]].size<x)	x-=tree[tree[now].ch[0]].size+1,	now=tree[now].ch[1];
    		else	now=tree[now].ch[0];
    		pushdown(now);
    	}
    	return now;
    }
    inline void rotate(int x)
    {
    	int f=tree[x].fa;bool d=get(x);
    	if(f==root)	root=x,tree[x].fa=0;
    	else	connect(x,tree[f].fa,get(f));
    	connect(tree[x].ch[!d],f,d);
    	connect(f,x,!d);
    	update(f);
    }
    inline void splay(int x,int r)
    {
    	if(x==r)	return ;
    	for(int f;(f=tree[x].fa)!=r;)
    	{
    		if(tree[f].fa==r){rotate(x);break;}	
    		rotate( (get(x)==get(f))?f:x );	rotate(x);
    	}
    	update(x);
    }
    inline void out(int x)
    {
    	if(!x)	return ;
    	pushdown(x);
    	out(tree[x].ch[0]);
    	if(x!=1&&x!=n+2)	printf("%d ",x-1);
    	out(tree[x].ch[1]);
    }
    int main()
    {
    	freopen("sph.in","r",stdin);
    	freopen("sph.out","w",stdout);
    	read(n);read(m);
    	root=build(1,n+2);
    	int l,r,tmp;
    	for(int i=1;i<=m;i++)
    	{
    		read(l);read(r);
    		splay(find(l),0);
    		tmp=find(r+2);	splay(tmp,root);
    		tree[tree[tmp].ch[0]].rev^=1;
    	}
    	out(root);
    	return 0;
    }
    

      

  • 相关阅读:
    Study From DevOps 学习交流会议
    GS 服务器超时时间设置
    k8s 实验过程中遇到的两个小问题 端口 和 批量删除Error的pods
    这两天学到的简单Linux的命令
    Prometheus 和 Grafana的简单学习
    jenkins 添加 k8s 云
    常用的cpl 命令 运行直接打开控制台的简单方法
    [转贴] VIM 常用快捷键 --一直记不住
    [转载] 什么是istio 官网内容
    微软补丁201807补丁惹祸
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/7323663.html
Copyright © 2020-2023  润新知