• JZYZOJ1998 [bzoj3223] 文艺平衡树 splay 平衡树


    http://172.20.6.3/Problem_Show.asp?id=1998

    平衡树区间翻转的板子,重新写一遍,给自己码一个板子。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 #include<cstdlib>
      7 using namespace std;
      8 const int maxn=100100;
      9 int c[maxn][2],fa[maxn],siz[maxn],rev[maxn];
     10 int n,m,rt;
     11 inline int read(){
     12     int x=0,f=1;char ch=getchar();
     13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     14     while(ch>='0'&&ch<='9'){x*=10;x+=ch-'0';ch=getchar();}
     15     return x*f;
     16 }
     17 inline void pushup(int x){//向上总结siz
     18     siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;
     19 }
     20 inline void pushdown(int x){//向下传递rev标记
     21     if(rev[x]){
     22         swap(c[x][0],c[x][1]);
     23         rev[c[x][0]]^=1;rev[c[x][1]]^=1;
     24         rev[x]=0;
     25     }
     26 }
     27 void build(int l,int r,int pa){//不完全二分建树。。
     28     if(l>r)return;
     29     if(l==r){
     30         fa[l]=pa;siz[l]=1;
     31         if(l<pa)c[pa][0]=l;
     32         else c[pa][1]=l;
     33         return;
     34     }
     35     int mid=(l+r)/2;
     36     build(l,mid-1,mid);build(mid+1,r,mid);
     37     if(mid<pa)c[pa][0]=mid;
     38     else c[pa][1]=mid;
     39     fa[mid]=pa;
     40     pushup(mid);
     41 }
     42 int find(int x,int rank){//二分查找排名为rank的数
     43     //因为建树的时候已经默认查找的数在数组中的序号就是它本身
     44     //操作不会改变一个节点的序号,只会改变点和点的联系,从而改变排列顺序
     45     pushdown(x);
     46     //find中的pushdown相当于为后面的splay“开路”
     47     int l=c[x][0],r=c[x][1];
     48     if(siz[l]+1==rank)return x;
     49     else if(siz[l]>=rank)return find(l,rank);
     50     else return find(r,rank-siz[l]-1);
     51 }
     52 void rotate(int x,int &k){//向上旋转
     53     int pa=fa[x];int gpa=fa[pa],l,r;
     54     if(c[pa][0]==x) l=0;
     55     else l=1; r=l^1;//上旋前x在pa的l方向
     56     if(pa==k) k=x;
     57     else{
     58         //如果x旋转不到k,需要关注上旋后和gpa的儿子关系
     59         //观察后面的调用,旋转到k时gpa的儿子关系相当于直接被继承,
     60         if(c[gpa][0]==pa)c[gpa][0]=x;
     61         else c[gpa][1]=x;
     62     }
     63     fa[x]=gpa;fa[pa]=x;fa[c[x][r]]=pa;
     64     c[pa][l]=c[x][r];c[x][r]=pa;
     65     pushup(x);pushup(pa);
     66     
     67 }
     68 void splay(int x,int &k){
     69     while(x!=k){
     70         int pa=fa[x];int gpa=fa[pa];
     71         if(pa!=k){//这里的异或处理了顺位和逆位两种情况
     72             /*顺位先将pa上旋至k,逆位直接将x向上旋,
     73             避免树失衡。*/
     74             if((c[pa][0]==x)^(c[gpa][0]==pa))rotate(x,k);
     75             else rotate(pa,k);
     76         }rotate(x,k);
     77     }
     78 }
     79 void rever(int l,int r){
     80     int x=find(rt,l),y=find(rt,r+2);//找到两个数的位置
     81     splay(x,rt);splay(y,c[x][1]);//将两个数调为根和其rc
     82     //此时,两个数之间的数都在根的rc的lc上
     83     /*    我们开始开始的建树从1到n+2就是为了将1和n+2作为边界
     84     事实上进行操作的是2到n+1这n个数。我们最后取的时候要减1。
     85     所以,翻转l+1到r+1即可。
     86     */
     87     rev[c[y][0]]^=1;
     88 }
     89 int main(){
     90     n=read();m=read();
     91     int x,y;
     92     build(1,n+2,0);rt=(n+3)/2;
     93     for(int i=1;i<=m;i++){
     94         x=read();y=read();
     95         rever(x,y);
     96     }
     97     for(int i=2;i<=n+1;i++){
     98         printf("%d ",find(rt,i)-1);
     99     }
    100     return 0;
    101 }
    View Code
  • 相关阅读:
    老旧ObjectARX SDK下载地址
    AutoCAD Civil 3D .NET 二次开发 勘误
    lisp网站
    Autodesk论坛中看到的一段代码,留存备用
    revit图纸导出dxf文件批量修改
    查询给定区域内曲面平均高程
    angular 输入型指令directive
    get set方法
    android 环境配置
    使用nginx启动angular项目
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8349742.html
Copyright © 2020-2023  润新知