zoukankan      html  css  js  c++  java
  • bzoj 2002 弹飞绵羊 lct裸题

    上一次用分块过了, 今天换了一种lct(link-cut tree)的写法。

    学lct之前要先学过splay。

    lct 简单的来说就是 一颗树, 然后每次起作用的都是其中的某一条链

    所以每次如果需要用到一条链, 就要先 access 一下某个位置, 到root, 将其他的非法的东西抠掉。

    并且 一个很大的特点就是  假设现在有u,v2个节点, 存在一条边 u -> v, 那么 u 的 父亲指向 v 但是 v 不一定存在 儿子节点指向 u , 也就是说很多时候是单向边。

    然后对于整个lct来说, 他由很多个splay组成的。

    代码:

      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 tr[x].son[0]
     12 #define rch 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 = 2e5 + 100;
     20 int n, t;
     21 struct Node{
     22     int son[2], pre;
     23     int sz, is_root;
     24     inline void init() {
     25         son[1] = son[0] = pre = 0;
     26         sz = is_root =1;
     27     }
     28 }tr[N];
     29 void Push_Up(int x){
     30     if(!x) return ;
     31     tr[x].sz = tr[lch].sz + tr[rch].sz + 1;
     32 }
     33 void rotate(int x){
     34     if(tr[x].is_root) return ;
     35     int y = tr[x].pre, z = tr[y].pre;
     36     int k = x == tr[y].son[1];
     37     tr[y].son[k] = tr[x].son[k^1];
     38     tr[tr[y].son[k]].pre = y;
     39     tr[x].son[k^1] = y;
     40     tr[y].pre = x;
     41     tr[x].pre = z;
     42     if(tr[y].is_root) tr[x].is_root = 1, tr[y].is_root = 0;
     43     else tr[z].son[ tr[z].son[1] == y] = x;
     44     Push_Up(y);
     45     
     46 }
     47 void Splay(int x){
     48     while(!tr[x].is_root){
     49         int y = tr[x].pre, z = tr[y].pre;
     50         if(!tr[y].is_root){
     51             if((y == tr[z].son[1]) != ( x == tr[y].son[1])) rotate(y);
     52             else rotate(x);
     53         }
     54         rotate(x);
     55     }
     56     Push_Up(x);
     57 }
     58 void access(int x){
     59     int y = 0;
     60     do{
     61         Splay(x);
     62         tr[rch].is_root = 1;
     63         rch = y;
     64         tr[rch].is_root = 0;
     65         Push_Up(x);
     66         y = x;
     67         x = tr[x].pre;
     68     }while(x);
     69 }
     70 inline void link(int u, int v){
     71     if(v > n) v = 0;
     72     tr[u].pre = v;
     73 }
     74 inline void cut(int x){
     75     access(x);
     76     Splay(x);
     77     tr[lch].is_root = 1;
     78     tr[lch].pre = 0;
     79     lch = 0;
     80     Push_Up(x);
     81 }
     82 inline int Query(int x){
     83     access(x);
     84     Splay(x);
     85     return tr[lch].sz + 1;
     86 }
     87 int main(){
     88     scanf("%d", &n);
     89     for(int i = 1; i <= n; i++) tr[i].init();
     90     for(int i = 1; i <= n; i++){
     91         scanf("%d", &t);
     92         link(i, t+i);
     93     }
     94     int m, op, x, k;
     95     scanf("%d", &m);
     96     while(m--){
     97         scanf("%d", &op);
     98         if(op == 1) {
     99             scanf("%d", &x);
    100             printf("%d
    ", Query(x+1));
    101         }
    102         else {
    103             scanf("%d%d", &x, &k);
    104             cut(x+1);
    105             link(x+1, x+k+1);
    106         }
    107     }
    108     return 0;
    109 }
    View Code
  • 相关阅读:
    Shell基础一
    Hash表
    哈希表
    设置不输入密码ssh登录
    C++ int与string的转化
    mysql之数据类型
    ICE之C/S通信原理
    mysql基础入门
    SQL练习之不反复执行相同的计算
    SQL练习之求解填字游戏
  • 原文地址:https://www.cnblogs.com/MingSD/p/9475455.html
Copyright © 2011-2022 走看看