zoukankan      html  css  js  c++  java
  • bzoj 2049 [Sdoi2008]Cave 洞穴勘测(LCT)

    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=2049

    【题意】

        给定森林,可能有连边或断边的操作,回答若干个连通性的询问。

    【思路】

        Link-Cut-Tree。

        LCT的性质:

      1. 有一条重链上的所有节点构成的splay称作这条链的辅助树。

      2. 每个点的键值为这个点的深度。

      3. 链的辅助树的根的父亲指向链顶的父亲,然而链顶父亲的儿子并不指向链的辅助树的根。

      (我会告诉你上面是抄的Popoqqq大爷的PPT么

        LCT的操作:

        Access:切断原来的重儿子,将结点到原树根的路径变为重路径。先splay到辅助树的根,然后修改右儿子,只用修改ch[1],右儿子的fa不用改变。

        Evert:将u旋转至原树的根,因为执行完Access之后u只是辅助树的根,所以还需要splay至原树根。维护2性质,通过旋转之后u到根的路径反转,需要打上反转标记。

        Link:连接两个不相连的节点。将u旋转至原树的根,然后将u的fa设为v。注意这里的操作并不是合并splay而只是连接两棵辅助树。

        Cut:断开两个节点。将u旋转至跟,然后Access(v),splay(v),这时候u一定处于v的左子树,直接切断就行了。

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<iostream>
      5 using namespace std;
      6  
      7 const int N = 1e5+10;
      8  
      9 struct Node {
     10     Node *ch[2],*fa;
     11     int rev;
     12     Node() ;
     13     void reverse() {
     14         rev^=1;
     15         swap(ch[0],ch[1]);
     16     }
     17     void up_push() {
     18         if(fa->ch[0]==this||fa->ch[1]==this) 
     19             fa->up_push();
     20         if(rev) {
     21             ch[0]->reverse();
     22             ch[1]->reverse();
     23             rev=0;
     24         }
     25     }
     26     void maintain() {
     27     }
     28 };
     29 Node *null=new Node,T[N];
     30 Node::Node() { fa=ch[0]=ch[1]=null; rev=0; }
     31 
     32 void rot(Node* o,int d) {                        //将o点向上旋转,方向为d^1 
     33     Node *p=o->fa;
     34     p->ch[d]=o->ch[d^1];
     35     o->ch[d^1]->fa=p;
     36     o->ch[d^1]=p;
     37     o->fa=p->fa;
     38     if(p==p->fa->ch[0])
     39         p->fa->ch[0]=o;
     40     else if(p==p->fa->ch[1])
     41         p->fa->ch[1]=o;
     42     p->fa=o;
     43     p->maintain();
     44 }
     45 void splay(Node* o) {                            //自下向上旋转至[所属splay]的根 
     46     o->up_push();
     47     Node *nf,*nff;
     48     while(o->fa->ch[0]==o||o->fa->ch[1]==o) {    //判断是否是根 
     49         nf=o->fa,nff=nf->fa;
     50         if(o==nf->ch[0]) {
     51             if(nf==nff->ch[0]) rot(nf,0);
     52             rot(o,0);
     53         } else {
     54             if(nf==nff->ch[1]) rot(nf,1);
     55             rot(o,1);
     56         }
     57     }
     58     o->maintain();
     59 }
     60 void Access(Node* o) {
     61     Node* son=null;
     62     while(o!=null) {                            //将o到根的路径变为重路径即合并到一棵splay 
     63         splay(o);
     64         o->ch[1]=son;
     65         o->maintain();
     66         son=o; o=o->fa;
     67     }
     68 }
     69 void evert(Node* o) {                            //将o转到[整棵动态树]的根 
     70     Access(o);
     71     splay(o);
     72     o->reverse();
     73 }
     74 void Link(Node* u,Node* v) {
     75     evert(u);
     76     u->fa=v;                                    //辅助树的根指向链顶的父亲然而链顶的父亲并不指向根 
     77 }
     78 void Cut(Node* u,Node* v) {
     79     evert(u);
     80     Access(v),splay(v);
     81     v->ch[0]=u->fa=null;
     82     v->maintain();
     83 }
     84  
     85 int n,m;
     86  
     87 void query(Node* u,Node* v)
     88 {
     89     Access(u),splay(u);
     90     while(v->fa!=null) v=v->fa;
     91     if(u==v) puts("Yes");
     92     else puts("No");
     93 }
     94  
     95 int main()
     96 {
     97    // freopen("in.in","r",stdin);
     98    // freopen("out.out","w",stdout);
     99     null->fa=null->ch[0]=null->ch[1]=null;
    100     char op[20]; int u,v;
    101     scanf("%d%d",&n,&m);
    102     while(m--) {
    103         scanf("%s%d%d",&op,&u,&v);
    104         if(op[0]=='Q')
    105             query(&T[u],&T[v]);
    106         else if(op[0]=='C')
    107             Link(&T[u],&T[v]);
    108         else
    109             Cut(&T[u],&T[v]);
    110     }
    111     return 0;
    112 }
  • 相关阅读:
    Django入门
    RCNN 研究相关
    [Android UI]View滑动方式总结
    [Android UI]View基础知识
    [Android]Android开发艺术探索第1章笔记
    [Leetcode]017. Letter Combinations of a Phone Number
    java之this关键字
    POJ 1000 A+B
    [Leetcode]016. 3Sum Closest
    [Leetcode]015. 3Sum
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5319198.html
Copyright © 2011-2022 走看看