zoukankan      html  css  js  c++  java
  • bzoj2049 Cave 洞穴勘测 lct

    这里比上次多了几个操作。

    1. make_root(u)

      换根节点, 先access(u), 再splay(u),将u移动到splay树的最顶上, 现在这棵splay对于root来说 只有左子树上有东西, 右子树上没有东西, 那么交换一下左右子树, 再打个标记, 这样就变成了左子树没东西,右子树上有东西, 这样 u就变成根节点了。

    2.link(u,v)

          就是将 u 和 v 连在一起,我本来想的是直接把 Access(u), Splay(u), 再pre[u] = v就好了, 但是这样是不对的,

    假设 u -> x, z -> x  , x是原来lct u 的根, 现在我们只操作 Access(u), Splay(u) 在把 pre[u] = v, 这样看似连起来了, 但是判断z 和 v 的连通性的时候不能保证联通,我们要先转换根节点, 把 u 的lct变成一 u 为根的树, 然后在pre[u] = v, 就把2个树联通起来了。

    3.cut(u,v)  

    我本来的想法是 直接access(v) 然后 pre[v]等于0就好了。

    但是,你无法保证我们是pre[u] = v 还是 pre[v] = u。

    并且假设 在link的时候 pre[u] = v,你执行完access 之后 pre[u] 不一定等于 v 因为是一颗splay 所以就算你再Splay(u)之后 你的 左儿子也不一定就是v。 由于splay的性质。

    所以 我们需要makeroot(v) 再access(u) splay(u) 现在 在 splay u上面只有2个节点, u 和 v, 所以我们现在就确保了 u的左子树一定是v。

    4 Rev(u)

    这个函数出现在了 Splay的地方, 原因就是 你可能前面的某个节点执行了翻转, 由于lazy的原因, 我们需要把标记从上往下传, 所以我们就需要先找到这棵splay的根, 然后再一步一步把需要下穿的lazy传过来。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
      4 #define LL long long
      5 #define ULL unsigned LL
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define lson l,m,rt<<1
     10 #define rson m+1,r,rt<<1|1
     11 #define lch(x) tr[x].son[0]
     12 #define rch(x) tr[x].son[1]
     13 #define max3(a,b,c) max(a,max(b,c))
     14 #define min3(a,b,c) min(a,min(b,c))
     15 typedef pair<int,int> pll;
     16 const int inf = 0x3f3f3f3f;
     17 const LL INF = 0x3f3f3f3f3f3f3f3f;
     18 const LL mod =  (int)1e9+7;
     19 const int N = 1e5 + 100;
     20 struct Node{
     21     int rev, rt;
     22     int son[2], pre;
     23     void init(){
     24         rt = 1; rev = pre = son[0] = son[1] = 0;
     25     }
     26 }tr[N];
     27 void Push_Rev(int x){
     28     if(!x) return ;
     29     swap(lch(x), rch(x));
     30     tr[x].rev ^= 1;
     31 }
     32 void Push_Up(int x){
     33 
     34 }
     35 void Push_Down(int x){
     36    if(tr[x].rev){
     37         tr[x].rev = 0;
     38         Push_Rev(lch(x));
     39         Push_Rev(rch(x));
     40     }
     41 }
     42 void Rev(int x){
     43     if(!tr[x].rt) Rev(tr[x].pre);
     44     Push_Down(x);
     45 }
     46 
     47 void rotate(int x){
     48     if(tr[x].rt) return;
     49     int y = tr[x].pre, z = tr[y].pre;
     50     int k = (rch(y) == x);
     51     tr[y].son[k] = tr[x].son[k^1];
     52     tr[tr[y].son[k]].pre = y;
     53     tr[x].son[k^1] = y;
     54     tr[y].pre = x;
     55     tr[x].pre = z;
     56     if(tr[y].rt) tr[y].rt = 0, tr[x].rt = 1;
     57     else tr[z].son[rch(z) == y] = x;
     58     Push_Up(y);
     59 }
     60 void Splay(int x){
     61      Rev(x);
     62      while(!tr[x].rt){
     63         int y = tr[x].pre, z = tr[y].pre;
     64         if(!tr[y].rt){
     65             if(( x == rch(y) ) != (y == rch(z))) rotate(y);
     66             else rotate(x);
     67         }
     68         rotate(x);
     69     }
     70     Push_Up(x);
     71 }
     72 void Access(int x){
     73     int y = 0;
     74     do{
     75         Splay(x);
     76         tr[rch(x)].rt = 1;
     77         rch(x) = y;
     78         tr[y].rt = 0;
     79         Push_Up(x);
     80         y = x;
     81         x = tr[x].pre;
     82     }while(x);
     83 }
     84 void Make_rt(int x){
     85     Access(x);
     86     Splay(x);
     87     Push_Rev(x);
     88 }
     89 void link(int u, int v){
     90     Make_rt(u);
     91     tr[u].pre = v;
     92 }
     93 void cut(int u, int v){
     94     Make_rt(u);
     95     Access(v);
     96     Splay(v);
     97     tr[lch(v)].pre = 0;
     98     tr[lch(v)].rt = 1;
     99     tr[v].pre = 0;
    100     lch(v) = 0;
    101 }
    102 bool judge(int u, int v){
    103     while(tr[u].pre) u = tr[u].pre;
    104     while(tr[v].pre) v = tr[v].pre;
    105     return u == v;
    106 }
    107 int n, m, u, v;
    108 char op[50];
    109 int main(){
    110     scanf("%d%d", &n, &m);
    111     for(int i = 1; i <= n; i++){
    112         tr[i].init();
    113     }
    114 
    115     while(m--){
    116         scanf("%s%d%d", op, &u, &v);
    117         if(op[0] == 'Q'){
    118             if(judge(u,v)) puts("Yes");
    119             else puts("No");
    120         }
    121         else if(op[0] == 'C') link(u,v);
    122         else cut(u,v);
    123     }
    124     return 0;
    125 }
    View Code
  • 相关阅读:
    BZOJ 2005 能量采集
    HDU 2841 Visible Trees(莫比乌斯反演)
    hihocoder 1543
    hihocoder 1311
    hdu 6069
    hdu 6058
    hdu 6034
    拓展欧几里得
    poj 3321
    树状数组总结
  • 原文地址:https://www.cnblogs.com/MingSD/p/9485739.html
Copyright © 2011-2022 走看看