bzoj 3223 Tyvj 1729 文艺平衡树 [Splay]

19 篇文章 0 订阅
7 篇文章 0 订阅

文艺平衡树

Time Limit: 10 Sec
Memory Limit: 128 MB
Submit: 3386 Solved: 1916

Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1

Input
第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n) m表示翻转操作次数
接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n

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

Sample Input
5 3
1 3
1 3
1 4

Sample Output
4 3 2 1 5

HINT
N,M<=100000


Splay细节太多。。建树的时候 l>r 要return!!
然后就是注意update!!
以及最后遍历的时候注意标记下放!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<climits>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
const int INF=0x3f3f3f3f;
const int maxn = 100005;
struct Node
{
    int val;
    int size;
    int fa,ch[2];
    bool rev;
}node[maxn];
int root;
#define val(x) node[x].val
#define size(x) node[x].size
#define fa(x) node[x].fa
#define ch(x,d) node[x].ch[d]
#define rev(x) node[x].rev
inline void update(int x)
{
    int l=ch(x,0),r=ch(x,1);
    size(x)=1;
    if(l) size(x) += size(l);
    if(r) size(x) += size(r);
}
void rotate(int x,int &to)
{
    int y=fa(x),z=fa(y);
    int l= ch(y,1)==x , r=l^1;
    if(y==to) to = x;
    else ch(z,ch(z,1)==y) = x;
    fa(ch(x,r))=y; fa(y)=x; fa(x)=z;
    ch(y,l)=ch(x,r); ch(x,r)=y;
    update(y); update(x);
}
void splay(int x,int &to)
{
    while(x^to)
    {
        int y=fa(x),z=fa(y);
        if(y^to)
            if(ch(y,0)==x ^ ch(z,0)==y) rotate(x,to);
            else rotate(y,to);
        rotate(x,to);
    }
}
void pushdown(int x)
{
    if(!rev(x)) return;
    rev(x)^=1;
    int l=ch(x,0),r=ch(x,1);
    if(l) swap(ch(l,0),ch(l,1)),rev(l)^=1;
    if(r) swap(ch(r,0),ch(r,1)),rev(r)^=1;
}
int find(int x,int k)
{
    pushdown(x);
    int lsize=size(ch(x,0));
    if(lsize+1==k) return x;
    if(k<=lsize) return find(ch(x,0),k);
    else return find(ch(x,1),k-lsize-1);
}
int split(int s,int t) // original array
{
    int x=find(root,s),y=find(root,t+2);
    splay(x,root); splay(y,ch(x,1));
    return ch(y,0);
}
void reverse(int s,int t)
{
    int rt = split(s,t);
    swap(ch(rt,0),ch(rt,1));
    rev(rt) ^= 1;
}
int n,m;
int a[maxn];
void build(int l,int r,int f)
{
    if(l>r) return; // must !! or RE!!
    int m=(l+r)>>1;
    if(l^r) build(l,m-1,m),build(m+1,r,m);
    fa(m)=f;
    ch(f,m>f)=m; // !!
    val(m)=a[m];
    update(m); // !!
}
void print_in(int x)
{
    if(!x) return;
    pushdown(x); // must !! probably to be lazyed!
    print_in(ch(x,0));
    if(val(x)^INF) printf("%d ",val(x));
    print_in(ch(x,1));
}
int main()
{
    freopen("splay.in","r",stdin);
    freopen("splay.out","w",stdout);
    scanf("%d%d",&n,&m);
    a[1]=a[n+2]=INF;
    for(int i=1;i<=n;i++) a[i+1]=i;
    build(1,n+2,0);
    root = (n+3)>>1;
    for(int i=1;i<=m;i++)
    {
        int s,t;
        scanf("%d%d",&s,&t);
        reverse(s,t);
        //print_in(root);cout<<endl;
    }
    print_in(root);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值