洛谷P3391 【模板】文艺平衡树(Splay)(FHQ Treap)

题目背景

这是一道经典的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,?n−1,n) m表示翻转操作次数

接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r \leq n1≤l≤r≤n

输出格式:

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

输入输出样例

输入样例#1: 复制

5 3
1 3
1 3
1 4

输出样例#1: 复制

4 3 2 1 5

说明

n, m \leq 100000n,m≤100000

FHQ无敌,

解决区间问题的时候按照$r$分成两个

再按照$l$分成两个

那么我们就得到了需要翻转的区间

然后愉快的打标记就好啦

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<ctime>
  5 #include<cstdlib>
  6 using namespace std;
  7 #define ls T[now].ch[0]
  8 #define rs T[now].ch[1]
  9 const int MAXN=1e6+10;
 10 inline char nc()
 11 {
 12     static char buf[MAXN],*p1=buf,*p2=buf;
 13     return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
 14 }
 15 inline int read()
 16 {
 17     char c=nc();int x=0,f=1;
 18     while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=nc();}
 19     while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘,c=nc();}
 20     return x*f;
 21 }
 22 struct node
 23 {
 24     int ch[2],val,siz,pri,mark;
 25 }T[MAXN];
 26 int tot=0;
 27 int x,y,z,root=0,n,m;
 28 int newnode(int v)
 29 {
 30     T[++tot].siz=1;
 31     T[tot].val=v;
 32     T[tot].pri=rand();
 33     return tot;
 34 }
 35 void update(int now)
 36 {
 37     T[now].siz=T[ls].siz+T[rs].siz+1;
 38 }
 39 int Build(int l,int r)
 40 {
 41     if(l>r)    return 0;
 42     int mid=(l+r)>>1;
 43     int now=newnode(mid-1);
 44     ls=Build(l,mid-1);
 45     rs=Build(mid+1,r);
 46     update(now);
 47     return now;
 48 }
 49 void pushdown(int now)
 50 {
 51     if(T[now].mark&&now)
 52     {
 53         swap(ls,rs);
 54         if(ls)    T[ls].mark^=1;
 55         if(rs)    T[rs].mark^=1;
 56         T[now].mark=0;
 57     }
 58 }
 59 void split(int now,int k,int &x,int &y)
 60 {
 61     if(!now)    {x=y=0;return ;}
 62     pushdown(now);
 63     if(T[ls].siz<k)
 64         x=now,split(rs,k-T[ls].siz-1,rs,y);
 65     else
 66         y=now,split(ls,k,x,ls);
 67     update(now);
 68 }
 69 int merge(int x,int y)
 70 {
 71     if(!x||!y)    return x+y;
 72     pushdown(x);pushdown(y);
 73     if(T[x].pri<T[y].pri)
 74     {
 75         T[x].ch[1]=merge(T[x].ch[1],y);
 76         update(x);
 77         return x;
 78     }
 79     else
 80     {
 81         T[y].ch[0]=merge(x,T[y].ch[0]);
 82         update(y);
 83         return y;
 84     }
 85 }
 86 void dfs(int now)
 87 {
 88     pushdown(now);
 89     if(T[now].ch[0]) dfs(T[now].ch[0]);
 90     if(T[now].val>=1&&T[now].val<=n)    printf("%d ",T[now].val);
 91     if(T[now].ch[1]) dfs(T[now].ch[1]);
 92 }
 93 int main()
 94 {
 95     #ifdef WIN32
 96     freopen("a.in","r",stdin);
 97     #else
 98     #endif
 99     //srand((unsigned)time(NULL));
100     n=read(),m=read();
101     root=Build(1,n+2);
102     while(m--)
103     {
104         int l=read(),r=read();
105         int a,b,c,d;
106         split(root,r+1,a,b);
107         split(a,l,c,d);
108         T[d].mark^=1;
109         root=merge( merge(c,d) ,b );
110     }
111     dfs(root);
112     return 0;
113 }
时间: 2024-10-02 11:26:06

洛谷P3391 【模板】文艺平衡树(Splay)(FHQ Treap)的相关文章

洛谷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,?n−1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r

洛谷 P3391 【模板】文艺平衡树(Splay)

题目背景 这是一道经典的Splay模板题--文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是 (1,2,?n?1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1≤l≤r≤n 输出格式: 输出一行n个数字,表示原始序列经过m次变换后的结果

AC日记——文艺平衡树 洛谷 P3391

文艺平衡树 思路: splay翻转操作模板: 虚拟最左最右端点,然后每次都把l翻转到root,r+2翻转到root的右节点: 然后在r+2的左节点上打标记: 标记需要在旋转,rank,print时下放: 建树需要用完全平衡二叉树: 来,上代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define m

Tyvj P1729 文艺平衡树 Splay

题目: http://tyvj.cn/p/1729 P1729 文艺平衡树 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 此为平衡树系列第二道:文艺平衡树 描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入格式 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数

BZOJ3223: Tyvj 1729 文艺平衡树 [splay]

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3595  Solved: 2029[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

洛谷3380 二逼平衡树(树套树)

题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数值 查询k在区间内的前驱(前驱定义为严格小于x,且最大的数,若不存在输出-2147483647) 查询k在区间内的后继(后继定义为严格大于x,且最小的数,若不存在输出2147483647) 注意上面两条要求和tyvj或者bzoj不一样,请注意 输入输出格式 输入格式: 第一行两个数 n,m 表示长度为n的有序序列和m个操作 第二行有n个数,

【C++】最近公共祖先LCA(Tarjan离线算法)&amp;&amp; 洛谷P3379LCA模板

1.前言 首先我们介绍的算法是LCA问题中的离线算法-Tarjan算法,该算法采用DFS+并查集,再看此算法之前首先你得知道并查集(尽管我相信你如果知道这个的话肯定是知道并查集的),Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解(个人认为). 2.思想 下面详细介绍一下Tarjan算法的思想: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5.寻找与当前点

AC自动机(附洛谷P3769模板题)

首先,介绍一下AC自动机(Aho-Corasick automaton),是一种在一个文本串中寻找每一个已给出的模式串的高效算法. 在学习AC自动机之前,你需要先学习Trie树和KMP算法,因为AC自动机正式利用并结合了两者的思想. 说到实际的不同,其实AC自动机只是在Trie树上引入了一个类似KMP中next数组的东西叫做Fail指针. 对于每一个节点,Fail指针指向该节点所代表的字符串中,次长的.在Trie树中存在的后缀(因为最长的在Trie树种存在的后缀就是其本身)所代表的节点. 举例:

洛谷P3375 [模板]KMP字符串匹配

To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整