BZOJ3153 Sone1 (Toptree)

上周看Lytning(鄙校一队某大佬)开了一个LCT的专题,里面有这个题,正好我也没怎么写过LCT维护子树的题,就决定拿这个题开刀。

先来说说LCT维护子树的大致思路,LCT里的轻边在Splay里都是只有儿子指向父亲但是父亲不指向儿子的虚边,如果维护的是树链,只用维护Splay里的实边,但是维护子树的话只要把每个节点的虚边也维护一下就行了。

我之前只写过不带修改的子树维护,不带修改只要把虚子树信息向上更新即可,但是要修改的话,就要有标记下放,标记下方的时候要对所有虚子树下放标记。如果用一个线性结构维护虚子树,就会被菊花图卡死,于是就想到用一个平衡树来维护所有的虚子树。这个就是传说中的Toptree。

但是我开了这个题之后,发现我进了一个无底洞,写题3小时,debug一星期,本来以为只是要维护的变量多了点而已,但是写的时候发现有一些细节不是很好处理。说一下主要遇到的几个问题,最开始遇到的问题是函数调用,前面的函数要调后面的函数,虽然我觉得这样不是很优雅,但是想了想也没啥好的解决办法。遇到的第二个问题,而是蒙蔽我时间最长的一个问题,我平衡树用的是Treap,但是我没写过标记下放的Treap,于是我在删节点的时候写残了,这个真是坑死我了。还有一个就是Splay和LCT的access(expose)过程中的标记下放,我之前Splay的标记下放都是边转边下放,网上其他大佬们的代码都是从根一路下放下来再转上去,可能我的写法是邪教吧,之前没出过问题,但是这个题就是不对,这个问题其实我现在还没明白为什么不对,希望有大佬知道的可以告诉我……

一些闲话,比如说STL的stack真的血慢,还有就是我的数据结构都是指针写的,虽然经常被学长喷卡内存啥的,但是BZOJ是32位机不怕嘿嘿嘿。

最后奉上我又臭又长的代码,基本上是照着mhy的代码改的

#include 
using namespace std;
const int MAXN = 100005, INF = 0x7fffffff;
struct Treap
{
    struct Node
    {
		int idx, pr, siz, maxv, minv, sumv, add, val;
		bool lazy;
		Node *child[2];
		inline int cmp(int) const;
		inline void maintain();
		inline void change_val(int);
		inline void add_val(int);
		inline void push_down();
    }pool[MAXN], *nil, *alloc;
    Node* new_Node(int);
    void init();
    void rotate(Node*&, int);
    void insert(Node*, Node*&);
    void erase(int, Node*&);
    void debug(Node*);
}treap;
struct Splay_tree
{
    struct Node
    {
        int idx;
        Treap::Node *root;
        Node *child[2], *parent;
        inline bool isroot() const;
        inline void maintain();
        inline void tree_change(int);
        inline void chain_change(int);
        inline void tree_add(int);
        inline void chain_add(int);
        inline void reverse();
        inline void push_down();
        inline void insert(Node*);
        inline void erase(Node*);
    }*nil, pool[MAXN], *alloc;
	Node* new_Node(int);
	void init();
	Node* find(Node*);
	void update(Node*);
	void rotate(Node*);
	void splay(Node*);
	Node* prec(Node*);
};
struct Record
{
    int key, cadd, tadd, cval, tval, csiz, tsiz,
        cmax, tmax, cmin, tmin, csum, tsum;
    bool flip, clazy, tlazy;
    Treap::Node* tr;
    Splay_tree::Node* sp;
}rec[MAXN], *alloc = rec;
int new_Record(int key)
{
    Record* ret = alloc++;
    ret->csiz = 1;
    ret->key = ret->cmax = ret->cmin = ret->csum = key;
    ret->tmax = -INF;
    ret->tmin = INF;
    ret->tsum = ret->tsiz = ret->cadd = ret->tadd = 0;
    ret->flip = ret->clazy = ret->tlazy = false;
    return ret - rec;
}
inline int Treap::Node::cmp(int v) const
{
    if (v == idx) return -1;
    else return v < idx ? 0 : 1;
}
inline void Treap::Node::maintain()
{
    siz = rec[idx].csiz + rec[idx].tsiz;
    maxv = max(rec[idx].cmax, rec[idx].tmax);
    minv = min(rec[idx].cmin, rec[idx].tmin);
    sumv = rec[idx].csum + rec[idx].tsum;
    for (int i = 0; i < 2; i++)
    {
        siz += child[i]->siz;
        maxv = max(maxv, child[i]->maxv);
        minv = min(minv, child[i]->minv);
        sumv += child[i]->sumv;
    }
}
inline void Treap::Node::change_val(int v)
{
    if (idx == 0) return;
    add = 0;
    lazy = true;
    val = maxv = minv = v;
    sumv = siz * v;
}
inline void Treap::Node::add_val(int v)
{
    if (idx == 0) return;
    add += v;
    maxv += v, minv += v;
    sumv += siz * v;
}
inline void Treap::Node::push_down()
{
    if (lazy)
    {
        rec[idx].sp->tree_change(val);
        rec[idx].sp->chain_change(val);
        child[0]->change_val(val);
        child[1]->change_val(val);
        lazy = false;
    }
    if (add)
    {
        rec[idx].sp->tree_add(add);
        rec[idx].sp->chain_add(add);
        child[0]->add_val(add);
        child[1]->add_val(add);
        add = 0;
    }
}
Treap::Node* Treap::new_Node(int idx)
{
    Node* ret = alloc++;
    ret->idx = idx;
    ret->pr = rand();
    ret->siz = 1;
    ret->maxv = ret->minv = ret->sumv = rec[idx].key;
    ret->add = ret->val = 0;
    ret->lazy = false;
    ret->child[0] = ret->child[1] = nil;
    return ret;
}
void Treap::init()
{
    alloc = pool;
    nil = alloc++;
    nil->idx = nil->pr = 0;
    nil->siz = nil->sumv = 0;
    nil->maxv = -INF;
    nil->minv = INF;
}
void Treap::rotate(Node* &x, int dir)
{//0 : 1 ? zag : zig
    Node* y = x->child[dir ^ 1];
    x->push_down(), y->push_down();
    x->child[dir ^ 1] = y->child[dir];
    y->child[dir] = x;
    x->maintain(), y->maintain();
    x = y;
}
void Treap::insert(Node* temp, Node* &curr)
{
    if (curr == nil) curr = temp;
    else
    {
        curr->push_down();
        int dir = (temp->idx < curr->idx ? 0 : 1);
        insert(temp, curr->child[dir]);
        if (curr->child[dir]->pr > curr->pr)
            rotate(curr, dir ^ 1);
    }
    curr->maintain();
}
void Treap::erase(int idx, Node* &curr)
{
    curr->push_down();
    int d = curr->cmp(idx);
    if (d == -1)
    {
        if (curr->child[0] == nil) curr = curr->child[1];
        else if (curr->child[1] == nil) curr = curr->child[0];
        else
        {
            int dir = (curr->child[0]->pr > curr->child[1]->pr ? 1 : 0);
            rotate(curr, dir);
            erase(idx, curr->child[dir]);
            curr->maintain();
        }
    }
    else
    {
        erase(idx, curr->child[d]);
        curr->maintain();
    }
}
void Treap::debug(Node* curr)
{
    if (curr == nil) return;
    curr->push_down();
    debug(curr->child[0]);
    debug(curr->child[1]);
}
inline bool Splay_tree::Node::isroot() const
{
    if (this->parent->idx == 0) return true;
    return this->parent->child[0] != this &&
        this->parent->child[1] != this;
}
inline void Splay_tree::Node::maintain()
{
    rec[idx].csiz = 1;
    rec[idx].cmax = rec[idx].cmin = rec[idx].csum = rec[idx].key;
    rec[idx].tsiz = root->siz;
    rec[idx].tmax = root->maxv;
    rec[idx].tmin = root->minv;
    rec[idx].tsum = root->sumv;
    for (int i = 0; i < 2; i++)
    {
        rec[idx].csiz += rec[child[i]->idx].csiz;
        rec[idx].cmax = max(rec[idx].cmax, rec[child[i]->idx].cmax);
        rec[idx].cmin = min(rec[idx].cmin, rec[child[i]->idx].cmin);
        rec[idx].csum += rec[child[i]->idx].csum;
        rec[idx].tsiz += rec[child[i]->idx].tsiz;
        rec[idx].tmax = max(rec[idx].tmax, rec[child[i]->idx].tmax);
        rec[idx].tmin = min(rec[idx].tmin, rec[child[i]->idx].tmin);
        rec[idx].tsum += rec[child[i]->idx].tsum;
    }
}
inline void Splay_tree::Node::tree_change(int v)
{
    if (rec[idx].tsiz == 0) return;
    rec[idx].tadd = 0;
    rec[idx].tlazy = true;
    rec[idx].tval = v;
    rec[idx].tmax = rec[idx].tmin = v;
    rec[idx].tsum = rec[idx].tsiz * v;
    root->change_val(v);
}
inline void Splay_tree::Node::chain_change(int v)
{
    if (idx == 0) return;
    rec[idx].cadd = 0;
    rec[idx].clazy = true;
    rec[idx].key = rec[idx].cval = rec[idx].cmax = rec[idx].cmin = v;
    rec[idx].csum = rec[idx].csiz * v;
}
inline void Splay_tree::Node::tree_add(int v)
{
    if (rec[idx].tsiz == 0) return;
    rec[idx].tadd += v;
    rec[idx].tmax += v, rec[idx].tmin += v;
    rec[idx].tsum += rec[idx].tsiz * v;
    root->add_val(v);
}
inline void Splay_tree::Node::chain_add(int v)
{
    if (idx == 0) return;
    rec[idx].key += v;
    rec[idx].cadd += v;
    rec[idx].cmax += v, rec[idx].cmin += v, rec[idx].csum += rec[idx].csiz * v;
}
inline void Splay_tree::Node::reverse()
{
    swap(child[0], child[1]);
    rec[idx].flip = !rec[idx].flip;
}
inline void Splay_tree::Node::push_down()
{
    for (int i = 0; i < 2; i++)
    {
        if (rec[idx].tlazy) child[i]->tree_change(rec[idx].tval);
        if (rec[idx].tadd) child[i]->tree_add(rec[idx].tadd);
        if (rec[idx].clazy) child[i]->chain_change(rec[idx].cval);
        if (rec[idx].cadd) child[i]->chain_add(rec[idx].cadd);
        if (rec[idx].flip) child[i]->reverse();
    }
    rec[idx].cadd = rec[idx].tadd = 0;
    rec[idx].flip = rec[idx].clazy = rec[idx].tlazy = false;
}
inline void Splay_tree::Node::insert(Node* x)
{
    treap.insert(rec[x->idx].tr, root);
}
inline void Splay_tree::Node::erase(Node* x)
{
    treap.erase(x->idx, root);
    rec[x->idx].tr->child[0] = rec[x->idx].tr->child[1] = treap.nil;
}
Splay_tree::Node* Splay_tree::new_Node(int key)
{
    Node* ret = alloc++;
    ret->idx = new_Record(key);
    rec[ret->idx].tr = treap.new_Node(ret->idx);
    rec[ret->idx].sp = ret;
    ret->root = treap.nil;
    ret->child[0] = ret->child[1] = ret->parent = nil;
    return ret;
}
void Splay_tree::init()
{
    alloc = pool;
    nil = alloc++;
    nil->idx = new_Record(0);
    rec[nil->idx].csiz = rec[nil->idx].tsiz = 0;
    rec[nil->idx].cmax = rec[nil->idx].tmax = -INF;
    rec[nil->idx].cmin = rec[nil->idx].tmin = INF;
    treap.init();
    rec[nil->idx].tr = nil->root = treap.nil;
}
Splay_tree::Node* Splay_tree::find(Node* curr)
{
    while (!curr->isroot()) curr = curr->parent;
    return curr;
}
void Splay_tree::update(Node* curr)
{
    if (!curr->isroot()) update(curr->parent);
    curr->push_down();
}
void Splay_tree::rotate(Node* x)
{//0 : 1 ? zag : zig
    Node* y = x->parent;
    y->push_down(), x->push_down();
    int dir = (y->child[0] == x ? 1 : 0);
    y->child[dir ^ 1] = x->child[dir];
    x->child[dir]->parent = y;
    x->parent = y->parent;
    if (!y->isroot())
    {
        if (y == y->parent->child[0])
            y->parent->child[0] = x;
        else y->parent->child[1] = x;
    }
    x->child[dir] = y;
    y->parent = x;
    y->maintain();
}
void Splay_tree::splay(Node* x)
{
    Node* temp = find(x);
    if (temp->parent != nil) temp->parent->erase(temp);
    update(x);
    while (!x->isroot())
    {
        Node *y = x->parent, *z = y->parent;
        if (!y->isroot())
        {
            if ((z->child[0] == y) == (y->child[0] == x))
                rotate(y);
            else rotate(x);
        }
        rotate(x);
    }
    x->maintain();
    if (x->parent != nil) x->parent->insert(x);
}
Splay_tree::Node* Splay_tree::prec(Node* curr)
{
    splay(curr);
    Node* ret = curr->child[0];
    while (ret != nil && ret->child[1] != nil)
    {
        ret = ret->child[1];
        ret->push_down();
    }
    return ret;
}
int n, m, r;
struct Link_Cut_tree
{
    Splay_tree tree;
	typedef Splay_tree::Node Node;
	Node* root[MAXN];
	void init(int* value, int n)
	{
		tree.init();
		for (int i = 1; i <= n; i++)
			root[i] = tree.new_Node(value[i]);
	}
	void update(Node* curr)
	{
	    if (curr->parent != tree.nil) update(curr->parent);
	    curr->push_down();
	}
	void access(int x)
	{
	    update(root[x]);
		for (Node *curr = root[x], *last = tree.nil;
			curr != tree.nil; last = curr, curr = curr->parent)
		{
			tree.splay(curr);
		    if (last != tree.nil) curr->erase(last);
			if (curr->child[1] != tree.nil) curr->insert(curr->child[1]);
			curr->child[1] = last;
			curr->maintain();
		}
		tree.splay(root[x]);
	}
	int find(int x)
	{
		access(x);
		Node* ret = root[x];
		while (ret->child[0] != tree.nil)
			ret = ret->child[0];
		return ret - tree.nil;
	}
	void be_root(int x)
	{
		access(x);
		root[x]->reverse();
	}
	void cut(int x)
	{
	    access(x);
		root[x]->child[0]->parent = tree.nil;
		root[x]->child[0] = tree.nil;
		root[x]->maintain();
	}
	void link(int x, int y)
	{
	    if (y == 0) return;
		be_root(x);
		access(y);
		root[x]->parent = root[y];
		root[y]->child[1] = root[x];
		root[y]->maintain();
	}
	void tree_change(int x, int v)
	{
	    access(x);
	    Node* y = tree.prec(root[x]);
	    if (y != tree.nil) tree.splay(y);
        root[x]->tree_change(v);
        root[x]->chain_change(v);
        if (y != tree.nil) y->maintain();
	}
	void chain_change(int x, int y, int v)
	{
	    be_root(x);
	    access(y);
	    root[y]->chain_change(v);
	}
	int tree_min(int x)
	{
	    access(x);
	    Node* y = tree.prec(root[x]);
	    if (y != tree.nil) tree.splay(y);
        return min(rec[root[x]->idx].cmin, rec[root[x]->idx].tmin);
	}
	int tree_max(int x)
	{
	    access(x);
	    Node* y = tree.prec(root[x]);
	    if (y != tree.nil) tree.splay(y);
        return max(rec[root[x]->idx].cmax, rec[root[x]->idx].tmax);
	}
	void tree_add(int x, int v)
	{
	    access(x);
	    Node* y = tree.prec(root[x]);
	    if (y != tree.nil) tree.splay(y);
	    root[x]->tree_add(v);
	    root[x]->chain_add(v);
        if (y != tree.nil) y->maintain();
	}
	void chain_add(int x, int y, int v)
	{
	    be_root(x);
	    access(y);
	    root[y]->chain_add(v);
	}
	int chain_min(int x, int y)
	{
	    be_root(x);
	    access(y);
	    return rec[root[y]->idx].cmin;
	}
	int chain_max(int x, int y)
	{
	    be_root(x);
	    access(y);
	    return rec[root[y]->idx].cmax;
	}
	void change_parent(int x, int y)
	{
	    access(x);
        Node* z = tree.prec(root[x]);
        cut(x);
        if (find(y) == x) link(x, z - tree.nil);
        else link(x, y);
	}
	int chain_sum(int x, int y)
	{
	    be_root(x);
	    access(y);
	    return rec[root[y]->idx].csum;
	}
	int tree_sum(int x)
	{
	    access(x);
	    Node* y = tree.prec(root[x]);
	    if (y != tree.nil) tree.splay(y);
	    return rec[root[x]->idx].csum + rec[root[x]->idx].tsum;
	}
}lct;
struct Edge
{
    int u, v;
}edges[MAXN];
int value[MAXN];
inline char getch()
{
	static const int siz = 1 << 15;
	static char buffer[siz], *s = buffer, *t = buffer;
	if (s == t) s = buffer, t = s + fread(buffer, 1, siz, stdin);
	return s == t ? 0 : *(s++);
}
inline int read(int& res)
{
	res = 0;
	char ch;
	do
	{
		ch = getch();
		if (ch == 0) return -1;
	} while (!isdigit(ch) && ch != '-');
	int sgn = 1;
	if (ch == '-')
    {
        sgn = -1;
        ch = getch();
    }
	do
	{
		res = res * 10 + ch - '0';
		ch = getch();
	} while (isdigit(ch));
	res *= sgn;
	return 1;
}
int main()
{
    read(n), read(m);
    for (int i = 1; i < n; i ++)
        read(edges[i].u), read(edges[i].v);
    for (int i = 1; i <= n; i ++)
        read(value[i]);
    lct.init(value, n);
    for (int i = 1; i < n; i ++)
        lct.link(edges[i].u, edges[i].v);
    read(r);
    while (m--)
    {
        int k, x, y, z;
        read(k);
        if (k == 0)
        {
            read(x), read(y);
            lct.be_root(r);
            lct.tree_change(x, y);
        }
        else if (k == 1) read(r);
        else if (k == 2)
        {
            read(x), read(y), read(z);
            lct.chain_change(x, y, z);
        }
        else if (k == 3)
        {
            read(x);
            lct.be_root(r);
            printf("%d\n", lct.tree_min(x));
        }
        else if (k == 4)
        {
            read(x);
            lct.be_root(r);
            printf("%d\n", lct.tree_max(x));
        }
        else if (k == 5)
        {
            read(x), read(y);
            lct.be_root(r);
            lct.tree_add(x, y);
        }
        else if (k == 6)
        {
            read(x), read(y), read(z);
            lct.chain_add(x, y, z);
        }
        else if (k == 7)
        {
            read(x), read(y);
            printf("%d\n", lct.chain_min(x, y));
        }
        else if (k == 8)
        {
            read(x), read(y);
            printf("%d\n", lct.chain_max(x, y));
        }
        else if (k == 9)
        {
            read(x), read(y);
            lct.be_root(r);
            lct.change_parent(x, y);
        }
        else if (k == 10)
        {
            read(x), read(y);
            printf("%d\n", lct.chain_sum(x, y));
        }
        else
        {
            read(x);
            lct.be_root(r);
            printf("%d\n", lct.tree_sum(x));
        }
    }
    return 0;
}


你可能感兴趣的:(题解)