首页 > 其他分享 >P3391 文艺平衡树 题解

P3391 文艺平衡树 题解

时间:2024-01-17 20:55:23浏览次数:20  
标签:rs int 题解 Treap 文艺 P3391 ls siz push

Question

P3391 文艺平衡树

写一种数据结构维护有序数列,需要完成以下操作:翻转一个区间,例如原有的序列是 \(5,3,3,2,1\),翻转区间是 \([2,4]\) 的话,结果是 \(5,2,3,4,1\)

Solution

这道题的表达是 \(Splay\) 但是 \(Splay\) 的代码实现比较困难,考虑使用 FHQ Treap。

先思考如何将一个序列翻转,将序列对应到一个 BST 上面,如果需要这个序列翻转,只需要把左右儿子呼唤,然后把儿子节点递归调用这个过程

那么 FHQ 就很容易实现 Treap 的分裂

如果需要翻转序列 \([L,R]\) 先把 Treap 分裂成 \([1,L-1],[L,R],[R,n]\) 三个部分,然后翻转 \([L,R]\) 这个子树,最后将三棵树合并

每次翻转 \([L,R]\) 会导致超时,只需要类似于线段树一样在节点上打上 \(Tag\) 标记,每次更新标记即可

Code

#include<bits/stdc++.h>
using namespace std;

struct Treap{
    int root=0;
    struct Node{
        int ls,rs; //左儿子,右儿子
        int val,pri; //键值,优先级
        int siz; //子树大小
        int lay; //懒标记
        Node(int v=0,int p=0):val(v),pri(p),siz(1),ls(0),rs(0),lay(0){}
    };
    vector<Node> t;
    Treap(int n) {t.assign(n+1,Node());t[0].siz=0;}

    void push_up(int x){t[x].siz=t[t[x].ls].siz+t[t[x].rs].siz+1;}

    void push_down(int x){
        if(t[x].lay){
            swap(t[x].ls,t[x].rs);
            t[t[x].ls].lay^=1; t[t[x].rs].lay^=1;
            t[x].lay=0;
        }
    }

    void split(int x,int k,int &L,int &R){ //排名分裂,返回:L 前 x 个数,R 其他数
        if(x==0){L=R=0;return ;}
        push_down(x);
        if(t[t[x].ls].siz+1 <= k){
            L=x;
            split(t[x].rs,k-t[t[x].ls].siz-1,t[x].rs,R);
        }
        else{
            R=x;
            split(t[x].ls,k,L,t[x].ls);
        }
        push_up(x);
    }

    int merge(int L,int R){
        if(L==0 || R==0) return L+R;
        if(t[L].pri > t[R].pri){
            push_down(L);
            t[L].rs = merge(t[L].rs,R);
            push_up(L);
            return L;
        }
        else{
            push_down(R);
            t[R].ls = merge(L,t[R].ls);
            push_up(R);
            return R;
        }
    }

    void inorder(int x){
        if(x==0) return ;
        push_down(x);
        inorder(t[x].ls);
        printf("%d ",t[x].val);
        inorder(t[x].rs);
    }
};

int main(){
    int n,m; scanf("%d%d",&n,&m);
    Treap T(n);
    for(int i=1;i<=n;i++){
        T.t[i]=Treap::Node(i,rand());
        T.root=T.merge(T.root,i);
    }
    while(m--){
        int l,r; scanf("%d%d",&l,&r);
        int L,R,p; //三颗树
        T.split(T.root,r,L,R);  
        T.split(L,l-1,L,p);
        T.t[p].lay^=1;
        T.root=T.merge(T.merge(L,p),R);
    }
    T.inorder(T.root);
    return 0;
}

标签:rs,int,题解,Treap,文艺,P3391,ls,siz,push
From: https://www.cnblogs.com/martian148/p/17971153

相关文章

  • CF1633A题解
    Div.7题面翻译给定\(t\)组数据。每组数据给定一个数\(n\)(\(10\len\le999\))。每次操作可以修改\(n\)任意一位上的数,将这一位上的数修改为\(0\sim9\)之间的任意数。要求使用最少的修改次数使这个数修改后是\(7\)的倍数,并且没有多余的前导\(0\)。输出修改后的数,如......
  • CF1637A题解
    SortingParts题面翻译给定一个长度为n的数组a。你可以执行恰好一次操作。每次操作选择一个在[1,n-1]内的整数len,然后将数组a中长度为len的前缀和长度为n-len的后缀分别排序。请判断是否能够通过操作,使得最终的数组a不满足\foralli\in[1,n),a_i<=a(i+1)。数据范......
  • [ARC169E] Avoid Boring Matches 题解
    题目链接首先考虑无解的情况,一个显然的观察是如果R的个数大于一半,那么无论如何都会出现两个R比赛的情况,小于一半时我们可以调整使得B全都在前面,显然有解。接下来问题变为找到最优可行解,但是状态的合法性不是显然的,我们先尝试判定这个问题。先考虑第一轮比赛,显然我们想让......
  • SP839Optimal Marks 题解
    part1:建图二进制异或,每一位互不干扰。所以对每一位分开来考虑。然后变成了一个经典的模型。当前每一个未确定点有两个选择:变成\(1\),变成\(0\);已经确定的点只能选它本身的值。于是构造思路非常套路了:构造虚点\(S\)、\(T\)。对于一个点\(u\),从\(S\)连向\(u\)一条边,值为......
  • ABC311_g One More Grid Task 题解
    题目链接:Atcoder或者洛谷对于解决二维区间内的最值类型问题,我们常常有一类特别好用的方法,就是悬线法,它可以看做是单调栈的子集,但更加好理解和书写。对于悬线法,我们有一个常见的模型,找出面积最大的符合题意的最大的矩形:例题P4147玉蟾宫。对于悬线法而言,我们需要理解什么是悬......
  • P2216 [HAOI2007] 理想的正方形 题解
    题目链接:理想的正方形比较明显的,我们可以用二维ST表解决,具体的二维ST表的实现,只需要知道一点:对于\(st[i][j][t]=max(i\simi+2^t,j\simj+2^t)\),表示的是如图所示的大正方形范围内的最值,它可以拆成从四个小正方形的左端点走\(2^{t-1}\)长的小正方形组成,预处理完直接查......
  • 【深入挖掘Java技术】「源码原理体系」盲点问题解析之HashMap工作原理全揭秘(上)
    知识盲点概念介绍HashMap是基于Map接口构建的数据结构,它以键值对的形式存储元素,允许键和值都为null。由于键的唯一性,HashMap中只能有一个键为null。HashMap的特点是元素的无序性和不重复性。注意,HashMap并不是线程安全的。在多线程环境下,如果不进行适当的同步处理,可能会导致数据不......
  • P9018 [USACO23JAN] Moo Route G 题解
    首先有一些性质。因为保证有解,所以\(a_i\)一定都是\(2\)的倍数(必须一来一回)。并且总的步数应该为\(\suma_i\)。先考虑\(n\le2\)的情况,这时我们可以分情况讨论。因为每一条线段都会被来回走两次,所以我们可以先把每一个数都除以\(2\)。若\(a=b\),则最优情况一定是形......
  • P9017 [USACO23JAN] Lights Off G 题解
    一次操作相当于把\(a\)异或上\(b\),修改开关的一位相当于将这一位异或上\(1\)。会发现一个很神奇的性质:初始开关对灯的影响和改变开关状态对灯的影响是独立的。而前者的影响是固定的,所以我们可以只考虑改变开关状态对灯的影响。假设一共需要\(k\)次操作能使所有灯关闭,如果我......
  • CF1876D Lexichromatography 题解
    Problem-D-CodeforcesLexichromatography-洛谷先注意读题:对于所有的值\(k\),在这个序列的任意子区间\([l,r]\)中,值为\(k\)且为红色的位置数减去值为\(k\)且为蓝色的位置数的绝对值不超过\(1\)注意是任意子区间这说明什么?说明如果只有第二个条件,我......