[luogu3391][文艺平衡树]

Posted wxyww

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu3391][文艺平衡树]相关的知识,希望对你有一定的参考价值。

思路

splay区间操作的裸题。

假如要对l-r这段区间操作,那么就先把l-1伸展到根节点,然后把r +1伸展为根的儿子。这样r + 1的左儿子就是要操作的区间了。只要在上面打上标记,以后每次查询的时候pushdown一下。

然后对于l-1和r+1节点可能不存在,所以可以放两个标兵元素。就是一个极小值一个极大值(合适即可)。

对于这道题。只要每次修改的时候,按照上面的方法进行伸展。然后打标机即可。打标记的方法就是用0/1来表示当前区间是否被翻转,每次翻转就将标记^1即可。

代码

/*
* @Author: wxyww
* @Date:   2018-12-09 08:43:41
* @Last Modified time: 2018-12-09 11:00:52
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<bitset>
using namespace std;
#define ls TR[cur].ch[0]
#define rs TR[cur].ch[1]
typedef long long ll;
const int N = 100000 + 100;
ll read() {
    ll x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
int rt,tot,n,m;
struct node {
    int val,ch[2],lazy,siz,pre;
}TR[N];
void pushup(int cur) {
    TR[cur].siz = TR[ls].siz + TR[rs].siz + 1;
}
void pushdown(int cur) {
    if(TR[cur].lazy) {
        TR[ls].lazy ^= 1;
        TR[rs].lazy ^= 1;
        TR[cur].lazy ^= 1;
        swap(ls,rs);
    }
}
int build(int l,int r,int father) {
    if(l > r) return 0;
    int cur = (l + r) >> 1;
    TR[cur].val = cur - 1;
    TR[cur].pre = father;
    TR[cur].siz = 1;
    ls = build(l,cur - 1,cur);
    rs = build(cur + 1,r,cur);
    pushup(cur);
    return cur;
}
int getwh(int cur) {
    return TR[TR[cur].pre].ch[1] == cur;
}
void rotate(int cur) {
    int fa = TR[cur].pre,gr = TR[fa].pre;
    int f = getwh(cur);
    TR[gr].ch[getwh(fa)] = cur;
    TR[cur].pre = gr;
    TR[fa].ch[f] = TR[cur].ch[f ^ 1];
    TR[TR[cur].ch[f ^ 1]].pre = fa;
    TR[fa].pre = cur;
    TR[cur].ch[f ^ 1] = fa;
    pushup(fa);
    pushup(cur);
}
void splay(int cur,int to) {
    while(TR[cur].pre != to) {
        if(TR[TR[cur].pre].pre != to) {
            if(getwh(TR[cur].pre) != getwh(cur)) rotate(TR[cur].pre);
            else rotate(cur);
        }
        rotate(cur);
    }
    if(!to) rt = cur;
}
int kth(int now) {
    int cur = rt;
    while(cur) {
        pushdown(cur);
        if(now <= TR[ls].siz) cur = ls;
        else if(now > TR[ls].siz + 1) now -= TR[ls].siz + 1,cur = rs;
        else return cur; 
    }
}
void work(int l,int r) {
    int k1 = kth(l),k2 = kth(r + 2);
    splay(k1,0);
    splay(k2,k1);
    TR[TR[k2].ch[0]].lazy ^= 1;
    pushdown(TR[k2].ch[0]);
}
void print(int cur) {
    if(!cur) return;
    pushdown(cur);
    print(ls);
    if(TR[cur].val != 0 && TR[cur].val != n + 1)
    printf("%d ",TR[cur].val);
    print(rs);
}
int main() {
    n = read(),m = read();
    rt = build(1,n + 2,0);
    while(m--) {
        int l = read(),r = read();
        work(l,r);
    }
    print(rt);
    return 0;
}

一言

有伤害人的人存在的话,也会有能抚慰伤痕的人

以上是关于[luogu3391][文艺平衡树]的主要内容,如果未能解决你的问题,请参考以下文章

[Splay]luogu P3391 文艺平衡树

[luogu3391][文艺平衡树]

[luogu3391] 模板文艺平衡树(fhq-treap反转区间)

文艺平衡树

P3391 模板文艺平衡树(Splay)

P3391 模板文艺平衡树(Splay)新板子