码迷,mamicode.com
首页 > 其他好文 > 详细

Splay区间翻转(BZOJ3223)

时间:2016-08-07 15:18:40      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:

#include <cstdio>
#include <iostream>
using namespace std;

  const int nil=2*1e5;//nil表示不存在的节点
  int son[200001][2],flag[200001],size[200001],v[200001];
  int n,m; 
  int root,cnt,fa[200001];

  inline void swap(int &a,int &b){
      int t=a;
      a=b;b=t;
  }

  inline void mark(int po){
      swap(son[po][0],son[po][1]);
      flag[po]^=1;
  }
  
  inline void pushdown(int po){
      int l=son[po][0],r=son[po][1];
      if (flag[po]){
      if (l!=nil) mark(l);
      if (r!=nil) mark(r);
      flag[po]^=1;    
    }
  }
  
  inline int find(int num){
      int po=root;
      while (1){
        pushdown(po);
        if (size[son[po][0]]+v[po]==num) {return(po);continue;}
        if (size[son[po][0]]+v[po]>num)  {po=son[po][0];continue;}
        if (size[son[po][0]]+v[po]<num)  {num-=size[son[po][0]]+v[po],po=son[po][1];continue;}
    }
  }
 
  int build(int l,int r){
      int mid=(l+r)>>1;
      size[mid]=min(r,n)-max(l,1)+1; 
      son[mid][0]=son[mid][1]=nil;
      
      if (l<mid){
        son[mid][0]=build(l,mid-1);    
        fa[son[mid][0]]=mid;
      }
    
      if (r>mid){
        son[mid][1]=build(mid+1,r);
        fa[son[mid][1]]=mid;
      } 
    
    return(mid);
  }//建树时加入权值为0的0号点,权值为1的n+1号点,保证翻转l=1或r=n+1的操作正常进行
  
  void rotate(int po,int s){
      int f=fa[po];
      pushdown(po);
      son[f][s]=son[po][s^1];
      if (son[po][s^1]!=nil) fa[son[po][s^1]]=f;
      if (f==root) root=po;else 
        if (f==son[fa[f]][0]) son[fa[f]][0]=po;else
        son[fa[f]][1]=po;
      fa[po]=fa[f];
      fa[f]=po;
      son[po][s^1]=f;
      size[f]=size[son[f][0]]+size[son[f][1]]+v[f];
      size[po]=size[son[po][0]]+size[son[po][1]]+v[po];
  }
  
  void splay(int po,int targ){
      while (fa[po]!=targ){
        if (fa[fa[po]]==targ) {rotate(po,(po==son[fa[po]][1]));continue;} 
        int u,v;
        if (po==son[fa[po]][1]) u=1;else u=-1;
        if (fa[po]==son[fa[fa[po]]][1]) v=1;else v=-1;
        if (u*v==1){
            rotate(fa[po],(fa[po]==son[fa[fa[po]]][1]));
            rotate(po,(po==son[fa[po]][1]));
      };
      if (u*v==-1){
          rotate(po,(po==son[fa[po]][1]));
          rotate(po,(po==son[fa[po]][1]));
      }
    }
    size[po]=size[son[po][0]]+size[son[po][1]]+v[po];    
  }
   
  void reverse(int l,int r){
      int p=find(l-1);
    splay(p,nil);
      p=find(r+1);
    splay(p,root);
      mark(son[son[root][1]][0]);
  }

  int main(){
      freopen("a.in","r",stdin);
      
      scanf("%d%d",&n,&m);
      
      for (int i=1;i<=n;i++) v[i]=1;
      v[0]=0;v[n+1]=1;
      root=build(0,n+1);
      fa[root]=nil;

      
      for (int i=1;i<=m;i++){
        int l,r;
        scanf("%d%d",&l,&r);
        reverse(l,r);
    }
    
    for (int i=1;i<=n;i++) printf("%d ",find(i));
  }

 

Splay区间翻转(BZOJ3223)

标签:

原文地址:http://www.cnblogs.com/zhujiangning/p/5746141.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!