HDU 5002 Tree (2014年鞍山赛区网络赛F题)

1.题目描述:点击打开链接

2.解题思路:LCT的模板题

3.代码:

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

const int N = 111111;
const int INF = 1111111111;


int n, m;

class LCT {
private :
    struct node {
        int size, same, rev, val, inc;
        pair<int, int> value[2];
        node *child[2], *father;
        bool isRoot;
        inline void setChild(node *tmp, int dir) {
            child[dir] = tmp;
            tmp->father = this;
        }
        inline int isRc() {
            return father->child[1] == this;
        }
        
        int calc(int v) {
            int res = 0;
            if (val == v) {
                res++;
            }
            
            for(int i = 0; i < 2; i++)
                for(int j = 0; j < 2; j++) {
                    if (this->child[i]->value[j].first == v) {
                        res += this->child[i]->value[j].second;
                    }
                }
            return res;
        }
        
        inline void update() {
            if (size == 0) {
                return ;
            }
            int maxValue = max(val, max(child[0]->value[0].first, child[1]->value[0].first));
            value[0] = make_pair(maxValue, this->calc(maxValue));
            int sec = -INF;
            if (val != maxValue) {
                sec = max(sec, val);
            }
            for(int i = 0; i < 2; i++)
                for(int j = 0; j < 2; j++) {
                    if (this->child[i]->value[j].first != maxValue) {
                        sec = max(sec, this->child[i]->value[j].first);
                    }
                }
            value[1] = make_pair(sec, this->calc(sec));
            size = 1 + child[0]->size + child[1]->size;
        }
        
        inline void make(int v) {
            if (size == 0) {
                return ;
            }
            value[0] = make_pair(v, size);
            value[1] = make_pair(-INF, 0);
            same = v;
            inc = 0;
            val = v;
        }
        
        inline void add(int v) {
            if (size == 0) {
                return ;
            }
            inc += v;
            val += v;
            if (value[0].first != -INF) {
                value[0].first += v;
            }
            if (value[1].first != -INF) {
                value[1].first += v;
            }
        } 
        
        inline void reverse() {
            if (size == 0) {
                return ;
            }
            rev ^= 1;
            swap(child[0], child[1]);
        }
        
        inline void push() {
            if (size == 0) {
                return ;
            }
            if (rev) {
                child[0]->reverse();
                child[1]->reverse();
                rev = 0;
            }
            
            if (same != -INF) {
                child[0]->make(same);
                child[1]->make(same);
                same = -INF;
            }
            
            if (inc) {
                child[0]->add(inc);
                child[1]->add(inc);
                inc = 0;
            }
        }
    };
    typedef node *Node;
    node mem[N]; int used;
    Node Null, t[N];
    
    Node newNode(int v) {
        Node temp = &mem[used++];
        temp->size = 1, temp->same = -INF, temp->rev = 0, temp->val = v, temp->inc = 0;
        temp->value[0] = make_pair(v, 1);
        temp->value[1] = make_pair(-INF, 0);
        temp->child[0] = temp->child[1] = temp->father = Null;
        temp->isRoot = true;
        return temp;
    }
    
    
    void rotate(Node root) {
        Node father = root->father;
        father->push(); root->push();
        int dir = root->isRc();
        father->setChild(root->child[!dir], dir);
        if (father->isRoot) {
            father->isRoot = false;
            root->isRoot = true;
            root->father = father->father;
        } else {
            father->father->setChild(root, father->isRc());
        }
        root->setChild(father, !dir);
        father->update();
    }
    void splay(Node root) {
        for(root->push(); !root->isRoot; ) {
            if (root->father->isRoot) {
                rotate(root);
            } else {
                (root->isRc() == root->father->isRc()) ? 
                    (rotate(root->father), rotate(root)) : (rotate(root), rotate(root));
            }
        }
        root->update();
    } 
    void access(Node root, int oper = 0, int val = 0) {
        for(Node tmp(Null); root != Null; ) {
            splay(root);
            if (root->father == Null && oper) {
                if (oper == 1) {
                    tmp->make(val);
                    root->push();
                    root->child[1]->make(val);
                    root->val = val;
                    root->update();
                } else if (oper == 2) {
                    tmp->add(val);
                    root->push();
                    root->child[1]->add(val);
                    root->val += val;
                    root->update();
                }
            }
            root->child[1]->isRoot = true;
            root->child[1] = tmp;
            root->child[1]->isRoot = false;
            root->update();
            tmp = root;
            root = root->father;
        }
    }
public:
    void init(int n, int val[]) {
        used = 0;
        Null = newNode(-INF);
        Null->father = Null->child[0] = Null->child[1] = Null;
        Null->size = 0;
        for(int i = 1; i <= n; i++) {
            t[i] = newNode(val[i]);
        }
    }
    void Link(int son, int father) {
        access(t[son]);
        splay(t[son]);
        t[son]->father = t[father];
        t[son]->reverse();
    }
    void Cut(int u, int v) {
        access(t[v]);
        splay(t[u]);
        if (t[u]->father == t[v]) {
            t[u]->father = Null;
        } else {
            access(t[u]);
            splay(t[v]);
            if (t[v]->father == t[u]) {
                t[v]->father = Null;
            }
        }
    }
    
    void makeSame(int u, int v, int val) {
        access(t[u]);
        access(t[v], 1, val);
    }
    
    void add(int u, int v, int val) {
        access(t[u]);
        access(t[v], 2, val);
    }
    
    pair<int, int> getValue(int u, int v) {
        access(t[u]);
        Node root = t[v];
        pair<int, int> res;
        for(Node tmp(Null); root != Null; ) {
            splay(root);
            if (root->father == Null) {
                root->push();
                Node a = tmp, b = root->child[1];
                vector<int> vv;
                vv.push_back(root->val);
                for(int i = 0; i < 2; i++) {
                    vv.push_back(a->value[i].first);
                    vv.push_back(b->value[i].first);
                } 
                sort(vv.begin(), vv.end());
                vv.erase(unique(vv.begin(), vv.end()), vv.end());
                reverse(vv.begin(), vv.end());
                while(vv.size() && vv.back() == -INF) {
                    vv.pop_back();
                }
                if (vv.size() == 1) {
                    res = make_pair(-INF, 0);
                } else {
                    res = make_pair(vv[1], 0);
                    for(int i = 0; i < 2; i++) {
                        if (a->value[i].first == vv[1]) {
                            res.second += a->value[i].second;
                        }
                        if (b->value[i].first == vv[1]) {
                            res.second += b->value[i].second;
                        }
                    }
                    res.second += (root->val == vv[1]);
                }
            }
            root->child[1]->isRoot = true;
            root->child[1] = tmp;
            root->child[1]->isRoot = false;
            root->update();
            tmp = root;
            root = root->father;
        }
        return res;
    }
}tree;

int main() {
    int test;
    scanf("%d", &test);
    while(test--) {
        static int testCount = 0;
        printf("Case #%d:\n", ++testCount);
        scanf("%d %d", &n, &m);
        static int val[N];
        for(int i = 1; i <= n; i++) {
            scanf("%d", &val[i]);
        }
        tree.init(n, val);
        for(int i = 1; i < n; i++) {
            int a, b;
            scanf("%d %d", &a, &b);
            tree.Link(a, b);
        }
        for(int i = 1; i <= m; i++) {
            int type, a, b, x, y;
            scanf("%d", &type);
            if (type == 1) {
                scanf("%d %d %d %d", &x, &y, &a, &b);
                tree.Cut(x, y);
                tree.Link(a, b);
            } else if (type == 2) {
                scanf("%d %d %d", &a, &b, &x);
                tree.makeSame(a, b, x);
            } else if (type == 3) {
                scanf("%d %d %d", &a, &b, &x);
                tree.add(a, b, x);
            } else {
                int a, b;
                scanf("%d %d", &a, &b);
                pair<int, int> temp = tree.getValue(a, b);
                if (temp.first == -INF) {
                    printf("ALL SAME\n");
                } else {
                    printf("%d %d\n", temp.first, temp.second);
                }
            }
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值