zoukankan      html  css  js  c++  java
  • zoj3765Lights(splay)

    链接

    splay的增删改操作。

    刚开始对于某段区间首先有了lazy标记时,把其左右孩子给交换了,导致在pushup时又交换了一次而debug了n久。

      1 #include <iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<stdlib.h>
      6 #include<vector>
      7 #include<cmath>
      8 #include<queue>
      9 #include<set>
     10 using namespace std;
     11 #define N 300010
     12 #define LL long long
     13 #define INF 0xfffffff
     14 #define key_value ch[ch[root][1]][0]
     15 const double eps = 1e-8;
     16 const double pi = acos(-1.0);
     17 const double inf = ~0u>>2;
     18 using namespace std;
     19 int a[N][2];
     20 struct splay_tree
     21 {
     22     int pre[N],size[N],vv[N];
     23     int ch[N][2];
     24     int root,n,tot,num,tot1;
     25     int s[N][2],sta[N],key[N];
     26     void dfs(int x)
     27     {
     28         if(x)
     29         {
     30             dfs(ch[x][0]);
     31             printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d s0=%d  s1 = %d vv=%d
    ",
     32                    x,ch[x][0],ch[x][1],pre[x],size[x],key[x],s[x][0],s[x][1],vv[x]);
     33             dfs(ch[x][1]);
     34         }
     35     }
     36     void debug()
     37     {
     38         printf("root:%d
    ",root);
     39         dfs(root);
     40     }
     41 //以上用于debug*/
     42     void newnode(int &x,int v,int sta,int fa)//新建一结点
     43     {
     44         x = ++tot;
     45         ch[x][0]=ch[x][1] = 0;
     46         pre[x] = fa;
     47         s[x][0] = s[x][1] = 0;
     48         s[x][sta] = v;
     49         size[x] = 1;
     50         vv[x] = sta;
     51         key[x] = v;
     52     }
     53     void pushup(int w)//由儿子更新其父亲
     54     {
     55         size[w] = size[ch[w][0]]+size[ch[w][1]]+1;
     56         int st = vv[w];
     57         int l = ch[w][0],r = ch[w][1];
     58         int cnt1 = 0,cnt2 = 0;
     59         cnt1 = s[l][0];
     60         if(s[r][0])
     61         {
     62             if(cnt1) cnt1 = __gcd(s[r][0],cnt1);
     63             else cnt1 = s[r][0];
     64         }
     65         cnt2 = s[l][1];
     66         if(s[r][1])
     67         {
     68             if(cnt2) cnt2 = __gcd(s[r][1],cnt2);
     69             else cnt2 = s[r][1];
     70         }
     71         s[w][0] = cnt1,s[w][1] = cnt2;
     72         s[w][st] = s[w][st]?__gcd(s[w][st],key[w]):key[w];
     73         //cout<<s[w][0]<<" "<<s[w][1]<<endl;
     74     }
     75     void rotate(int r,int kind)//旋转操作,根据kind进行左旋和右旋
     76     {
     77         int y = pre[r];
     78         ch[y][!kind] = ch[r][kind];
     79         pre[ch[r][kind]] = y;
     80         if(pre[y])
     81         {
     82             ch[pre[y]][ch[pre[y]][1]==y] = r;
     83         }
     84         pre[r] = pre[y];
     85         ch[r][kind] = y;
     86         pre[y] = r;
     87         pushup(y);
     88         pushup(r);
     89     }
     90     void splay(int r,int goal)//将r结点旋至goal下
     91     {
     92         while(pre[r]!=goal)
     93         {
     94             if(pre[pre[r]]==goal)
     95             {
     96                 rotate(r,ch[pre[r]][0]==r);
     97             }
     98             else
     99             {
    100                 int y = pre[r];
    101                 int kind = (ch[pre[y]][0]==y);
    102                 if(ch[y][kind]==r)
    103                 {
    104                     rotate(r,!kind);
    105                     rotate(r,kind);
    106                 }
    107                 else
    108                 {
    109                     rotate(y,kind);
    110                     rotate(r,kind);
    111                 }
    112             }
    113         }
    114         pushup(r);
    115         if(goal==0) root = r;
    116     }
    117     int get_k(int k)//得到第k个的结点
    118     {
    119         int r = root;
    120         while(size[ch[r][0]]+1!=k)
    121         {
    122             if(size[ch[r][0]]>=k)
    123                 r = ch[r][0];
    124             else
    125             {
    126                 k-=(size[ch[r][0]]+1);//根据左右结点的数量来确定第k个节点在哪里
    127                 r = ch[r][1];
    128             }
    129         }
    130         pushup(r);
    131         return r;
    132     }
    133     void add(int k,int val,int sta)//添加一个结点 位置自己修改 这里为第一个
    134     {
    135         splay(get_k(k),0);
    136         splay(get_k(k+1),root);
    137         int r = ch[root][1];
    138         newnode(ch[r][0],val,sta,r);
    139         pushup(r);
    140         pushup(root);
    141     }
    142     void updelete(int r)//删除第r个结点
    143     {
    144         splay(get_k(r),0);
    145         splay(get_k(r+2),root);
    146         key_value = 0;
    147         pushup(ch[root][1]);
    148         pushup(root);
    149     }
    150     void update(int k,int flag,int v) //更新区间信息
    151     {
    152         splay(get_k(k),0);
    153         splay(get_k(k+2),root);
    154         if(flag)
    155         {
    156             vv[key_value]^=1;
    157             swap(s[key_value][1],s[key_value][0]);
    158         }
    159         else
    160         {key[key_value] = v;s[key_value][vv[key_value]] = v;}
    161         pushup(ch[root][1]);
    162         pushup(root);
    163 
    164     }
    165     int query(int l,int r,int sta)//询问l,r区间,将第l-1个结点旋自根,第r+1个结点旋自根的有儿子,
    166     {
    167         //则l-r就变成了根的右儿子的左儿子
    168         splay(get_k(l),0);
    169         splay(get_k(r+2),root);
    170         return s[key_value][sta];
    171     }
    172     void build(int &x,int l,int r,int fa)
    173     {
    174         int m = (l+r)>>1;
    175         if(l>r) return ;
    176         newnode(x,a[m][0],a[m][1],fa);
    177         build(ch[x][0],l,m-1,x);
    178         build(ch[x][1],m+1,r,x);
    179         pushup(x);
    180     }
    181     void init(int o)
    182     {
    183         int i;
    184         for(i = 1; i <= o; i++)
    185         scanf("%d%d",&a[i][0],&a[i][1]);
    186         size[0] = ch[0][0] = ch[0][1] = s[0][0] = s[0][1] = key[0] = vv[0] = 0;
    187         root = tot = 0;
    188         newnode(root,0,0,0);
    189         newnode(ch[root][1],0,0,root);
    190         build(ch[ch[root][1]][0],1,o,ch[root][1]);
    191         size[root] = 2;
    192         pushup(ch[root][1]);
    193         pushup(root);
    194     }
    195 }SP;
    196 int main()
    197 {
    198     int n,q;
    199     while(scanf("%d%d",&n,&q)!=EOF)
    200     {
    201         SP.init(n);
    202         while(q--)
    203         {
    204             char sq[20];
    205             int k,x,y;
    206             scanf("%s%d",sq,&k);
    207             if(sq[0]=='I')
    208             {
    209                 scanf("%d%d",&x,&y);
    210                 SP.add(k+1,x,y);
    211                // SP.debug();
    212             }
    213             else if(sq[0]=='D')
    214             {
    215                 SP.updelete(k);
    216             }
    217             else if(sq[0]=='R')
    218             {
    219                 SP.update(k,1,0);
    220             }
    221             else if(sq[0]=='M')
    222             {
    223                 scanf("%d",&x);
    224                 SP.update(k,0,x);
    225             }
    226             else if(sq[0]=='Q')
    227             {
    228                 scanf("%d%d",&x,&y);
    229                 int ans = SP.query(k,x,y);
    230                 if(ans==0)
    231                 printf("-1
    ");
    232                 else
    233                 printf("%d
    ",ans);
    234                // SP.debug();
    235             }
    236         }
    237     }
    238     return 0;
    239 }
    View Code
  • 相关阅读:
    virtualenvwrapper GitBash下的配置使用
    MySQL主从复制
    Nginx
    LVS
    MySQL
    Docker Swarm
    flask数据库操作
    flask 数据库迁移
    pytest.mark.parametrize 详解
    redis作为变量池在接口自动化中的应用
  • 原文地址:https://www.cnblogs.com/shangyu/p/3796717.html
Copyright © 2011-2022 走看看