bzoj 3223: Tyvj 1729 文艺平衡树(splay 模板题 区间翻转)

来源:互联网 发布:nero软件是否收费 编辑:程序博客网 时间:2024/05/18 02:26

3223: Tyvj 1729 文艺平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3321  Solved: 1887
[Submit][Status][Discuss]

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

Source

平衡树

[Submit][Status][Discuss]

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>using namespace std;int root,sz,n,m;int ch[100010][5],f[100010],size[100010],key[100010],a[100010],delta[100010];void swap(int &x,int &y){    int t;    t=x;  x=y;  y=t;}void updata(int x){    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}int get(int x){    return ch[f[x]][1]==x;}void pushdown(int x){    if (!x) return;    if (!delta[x]) return;    delta[ch[x][0]]^=1;    delta[ch[x][1]]^=1;    swap(ch[x][0],ch[x][1]);    delta[x]=0;}int build (int l,int r,int fa){    if (l>r) return 0;    int mid=(l+r)>>1;    int now=++sz;    ch[now][0]=build(l,mid-1,now);    ch[now][1]=build(mid+1,r,now);    f[now]=fa; delta[now]=0;    key[now]=a[mid];size[now]=size[ch[now][1]]+size[ch[now][0]]+1;    return now;} int find(int x){    int now=root;    while (true)     {        pushdown(now);        if (x<=size[ch[now][0]])         now=ch[now][0];        else         {            x-=(size[ch[now][0]]+1);            if (x==0)  return now;            now=ch[now][1];         }     }    return -1;}void rotate(int x){  pushdown(f[x]); pushdown(x);  int fa=f[x],oldfa=f[fa],which=get(x);  ch[fa][which]=ch[x][which^1];  f[ch[x][which^1]]=fa;  ch[x][which^1]=fa; f[fa]=x;  f[x]=oldfa;  if (oldfa)   ch[oldfa][ch[oldfa][1]==fa]=x;  updata(x); updata(fa);}void splay (int x,int l){    pushdown(x);    for (int fa;(fa=f[x])!=l;rotate(x))     if (f[fa]!=l)     rotate((get(fa)==get(x))?fa:x);    if (l==0)  root=x;}void print(int now){    pushdown(now);    if (ch[now][0]) print(ch[now][0]);    if (key[now]!=1000000000&&key[now]!=-1000000000)     printf("%d ",key[now]);    if (ch[now][1]) print(ch[now][1]); }int main(){    scanf("%d%d",&n,&m);    a[1]=-1000000000; a[n+2]=1000000000;    for (int i=1;i<=n;i++)     a[i+1]=i;    root=build(1,n+2,0);    for (int i=1;i<=m;i++)     {        int x,y;        scanf("%d%d",&x,&y);        int aa=find(x);        int bb=find(y+2);        splay(aa,0);        splay(bb,aa);        delta[ch[ch[root][1]][0]]^=1;     }    print(root);    printf("\n"); }



0 0
原创粉丝点击