zoukankan      html  css  js  c++  java
  • [Splay]luogu P3391 文艺平衡树

    题目描述

    https://www.luogu.org/problemnew/show/P3391

    分析

    文艺平衡树 一道大家熟知的splay区间翻转模板题

    基于splay的区间翻转,我们要做的只有这些:

    1、像线段树一样打翻转标记,不过由于翻转是可以抵消的,所以可以采取位运算节省时间

    2、翻转只需要逐层翻转即可,正确性已有论证

    3、对于区间如何确定的问题,我们只需要将l-1节点旋至根,r+1节点旋至根下即可

    4、对于1~x或x~n区间的操作,我们还需要0和n+1这两个哨兵节点

    #include <iostream>
    #include <cstdio>
    using namespace std;
    const int N=1e5+10;
    struct Node {
        int sz,val,f,c[2];
        bool rev;
    }t[N];
    int cnt,rt;
    int n,m;
    
    void Update(int x) {
        if (!x) return;
        t[x].sz=1+t[t[x].c[0]].sz+t[t[x].c[1]].sz;
    }
    
    void Pushdown(int x) {
        if (!x||!t[x].rev) return;
        t[t[x].c[0]].rev^=1;t[t[x].c[1]].rev^=1;
        int p=t[x].c[0];t[x].c[0]=t[x].c[1];t[x].c[1]=p;
        t[x].rev=0;
    }
    
    bool Witch(int x) {return t[t[x].f].c[1]==x;}
    
    void Rotate(int x) {
        int f=t[x].f,gf=t[f].f,lr=Witch(x);
        t[x].f=gf;if (gf) t[gf].c[Witch(f)]=x;
        t[f].c[lr]=t[x].c[lr^1];t[t[f].c[lr]].f=f;
        t[x].c[lr^1]=f;t[f].f=x;
        Update(f);Update(x);
    }
    
    void Splay(int x,int goal) {
        Pushdown(x);
        for (;t[x].f!=goal;Rotate(x))
            if (t[t[x].f].f!=goal)Rotate(Witch(t[x].f)==Witch(x)?t[x].f:x);
        if (!goal) rt=x;
        Update(x);
    }
    
    void Build(int &x,int l,int r) {
        if (l>r) return;
        if (!x) x=++cnt;
        int mid=l+r>>1;
        t[x].val=mid;t[x].sz=1;
        Build(t[x].c[0],l,mid-1);Build(t[x].c[1],mid+1,r);
        t[t[x].c[0]].f=t[t[x].c[1]].f=x;
        Update(x);
    }
    
    int Get(int x,int y,int goal) {
        Pushdown(x);
        if (t[t[x].c[0]].sz+1>y) return Get(t[x].c[0],y,goal);
        else {
            if (t[t[x].c[0]].sz+1==y) return x;
            return Get(t[x].c[1],y-t[t[x].c[0]].sz-1,goal);
        }
    }
    
    void Print(int x) {
        Pushdown(x);
        if (t[x].c[0]) Print(t[x].c[0]);
        if (t[x].val>=1&&t[x].val<=n)printf("%d ",t[x].val);
        if (t[x].c[1]) Print(t[x].c[1]);
    }
    
    void Change(int l,int r) {
        int x1,x2;
        x1=Get(rt,l,0);x2=Get(rt,r+2,rt);
        Splay(x1,0);Splay(x2,x1);Update(rt);
        t[t[x2].c[0]].rev^=1;
        Update(t[x2].c[0]);Update(x2);Update(rt);
    
    }
    
    int main() {
        scanf("%d%d",&n,&m);
        Build(rt,0,n+1);
        for (int i=1;i<=m;i++) {
            int l,r;
            scanf("%d%d",&l,&r);
            Change(l,r);
        }
        Print(rt);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    Memcached 测试
    Task WaitAll的用法
    Linux Memcached 安装
    开发常用的一些插件
    转:浅析VO、DTO、DO、PO的概念、区别和用处
    转:数据库的快照隔离级别(Snapshot Isolation)
    转:nolock的替代方案-提交读快照隔离[行版本控制]
    转:介绍一个好用的抓取dump的工具-ProcDump
    把sqlserver查询结果复制到Excel出现数据记录遗漏
    ASP.NET_SessionId 不相同导致验证码出错
  • 原文地址:https://www.cnblogs.com/mastervan/p/10293956.html
Copyright © 2011-2022 走看看