P3391 文艺平衡树(Splay做法)

摘要:
您需要编写一个数据结构来维护有序数组。需要提供以下操作:翻转间隔。例如,如果原始序列为5432154321,翻转间隔为[2,4][2,4],则结果为5234152341。

您需要写一种数据结构(可参考题目标题),来维护一个有序数列。

其中需要提供以下操作:翻转一个区间,例如原有序序列是 5 4 3 2 15 4 3 2 1,翻转区间是 [2,4][2,4] 的话,结果是 5 2 3 4 15 2 3 4 1。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
const int inf=1e9;
int n,m;
struct Splay_tree {
    int fa;
    int cnt;
    int ch[2];
    int v;
    int size;
    int lazy;
}t[maxn];
int root,tot;
void update (int x) {
    t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt;
}
void pushdown (int x) {
    if (t[x].lazy) {
        t[t[x].ch[0]].lazy^=1;
        t[t[x].ch[1]].lazy^=1;
        t[x].lazy=0;
        swap(t[x].ch[0],t[x].ch[1]);
    }
}
void rotate (int x) {
    int y=t[x].fa;
    int z=t[y].fa;
    int k=(t[y].ch[1]==x);
    t[z].ch[t[z].ch[1]==y]=x;
    t[x].fa=z;
    t[y].ch[k]=t[x].ch[k^1];
    t[t[x].ch[k^1]].fa=y;
    t[x].ch[k^1]=y;
    t[y].fa=x;
    update(y);
    update(x);
}
void splay (int x,int s) {
    while (t[x].fa!=s) {
        int y=t[x].fa;
        int z=t[y].fa;
        if (z!=s) 
            (t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);
        rotate(x);
    }
    if (s==0) root=x;
}
void find (int x) {
    int u=root;
    if (!u) return;
    while (t[u].ch[x>t[u].v]&&x!=t[u].v) 
        u=t[u].ch[x>t[u].v];
    splay(u,0);
}
void ins (int x) {
    int u=root;
    int fa=0;
    while (u&&t[u].v!=x) {
        fa=u;
        u=t[u].ch[x>t[u].v];
    }
    if (u)
        t[u].cnt++;
    else {
        u=++tot;
        if (fa)
            t[fa].ch[x>t[fa].v]=u;
        t[u].ch[0]=t[u].ch[1]=0;
        t[tot].fa=fa;
        t[tot].v=x;
        t[tot].cnt=1;
        t[tot].size=1;
    }
    splay(u,0); 
}
int Next (int x,int f) {
    find(x);
    int u=root;
    if (t[u].v>x&&f) return u;
    if (t[u].v<x&&!f) return u;
    u=t[u].ch[f];
    while (t[u].ch[f^1]) u=t[u].ch[f^1];
    return u;
} 
void del (int x) {
    int lst=Next(x,0);
    int nxt=Next(x,1);
    splay(lst,0);
    splay(nxt,lst);
    int tt=t[nxt].ch[0];
    if (t[tt].cnt>1) {
        t[tt].cnt--;
        splay(tt,0);
    }
    else 
        t[nxt].ch[0]=0;
}
int kth (int x) {
    int u=root;
    while (t[u].size<x) return 0;
    while (1) {
        pushdown(u);
        int y=t[u].ch[0];
        if (x>t[y].size+t[u].cnt) {
            x-=t[y].size+t[u].cnt;
            u=t[u].ch[1];
        }
        else if (t[y].size>=x) 
            u=y;
        else
            return t[u].v;
    }
}
void reverse (int l,int r) {
    l=kth(l);
    r=kth(r+2);
    splay(l,0);
    splay(r,l);
    t[t[t[root].ch[1]].ch[0]].lazy^=1; 
}
void dfs (int u) {
    pushdown(u);
    if (t[u].ch[0])
        dfs(t[u].ch[0]);
    if (t[u].v>1&&t[u].v<n+2)printf("%d ",t[u].v-1);
    if (t[u].ch[1])
        dfs(t[u].ch[1]);
}
int main () {
    scanf("%d%d",&n,&m);

    for (int i=1;i<=n+2;i++) ins(i);
    for (int i=1;i<=m;i++) {
        int l,r;
        scanf("%d%d",&l,&r);
        reverse(l,r);
    }
    dfs(root);
}

免责声明:文章转载自《P3391 文艺平衡树(Splay做法)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux的删除history的方法Linux 之不同运维人员共用root 账户权限审计下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

splay模板 指针版&amp;amp;splay被卡祭

普通平衡树板子 参考了大佬博客 访问空指针会出错,我用了一个nil代替他。(c++是谁设计的我还得把结构体定义在外面真难受) #include<bits/stdc++.h> using namespace std; typedef pair<int,int> pii; #define forg(i,x) for(int i=firs...

Qtree V

lmn u 表示 u 所在splay子树最上方点距离最近的白点 rmn u 表示 u 所在splay子树最下方点距离最近的白点 开一个set维护所有虚儿子能走到的最近的白点的距离 考虑pushup, 对于它的右儿子,考虑要么从这个点走向它的虚儿子,要么通过它左子树中深度最大的点走。 对于它的左儿子要么从这个点走向它的虚儿子,要么通过它右子树的最浅点走。 #...

ZJOI 2019 划水记

作为一个极其蒟蒻的OIer,虽然没有省选资格但还是去见见世面。 ZJOI2019一试是在浙江省镇海中学。听名字就很霸气。 学习OI的最后一年,记录下一些事情,即使最终走到最后也一无所获,也是一段美好的记忆吧。 起码,我努力过。 ——ljc20020730 Day -1 20190323 晚上复习下基础数论,写了十几个板子(excrt,exgcd什么的),写...

Splay算法基础与习题

前言 Spaly是基于二叉查找树实现的, 什么是二叉查找树呢?就是一棵树呗:joy: ,但是这棵树满足性质—一个节点的左孩子一定比它小,右孩子一定比它大 比如说 这就是一棵最基本二叉查找树 对于每次插入,它的期望复杂度大约是logn级别的,但是存在极端情况,比如9999999 9999998 9999997.....1这种数据,会直接被卡成n2 在这种情...