[bzoj3153] sone1 AC纪念

来源:互联网 发布:红米手机怎么清除数据 编辑:程序博客网 时间:2024/06/06 01:54

bzoj3153 sone1


历时两天A掉此题,特作纪念。


代码

#include <bits/stdc++.h>typedef long long LL;#define FOR(i, a, b) for (int i = (a), i##_END_ = (b); i <= i##_END_; i++)#define DNF(i, a, b) for (int i = (a), i##_END_ = (b); i >= i##_END_; i--)template <typename Tp> void in(Tp &x) {    char ch = getchar(), f = 1; x = 0;    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();    if (ch == '-') f = -1, ch = getchar();    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();    x *= f;}template <typename Tp> bool chkmax(Tp &x, Tp y) {return x > y ? 0 : (x=y,1);}template <typename Tp> bool chkmin(Tp &x, Tp y) {return x < y ? 0 : (x=y,1);}template <typename Tp> Tp Max(Tp x, Tp y) {return x > y ? x : y;}template <typename Tp> Tp Min(Tp x, Tp y) {return x < y ? x : y;}const int MAXN = 200010;struct Tag {    int k, b;    Tag(int k = 1, int b = 0): k(k), b(b) {}     Tag run(const Tag &another) const {        return Tag(k * another.k, b * another.k + another.b);    }};struct Data {    int minx, maxx, sum, sz;    Data(int sz = 0, int minx = 0x3f3f3f3f, int maxx = -0x3f3f3f3f, int sum = 0)        :minx(minx), maxx(maxx), sum(sum), sz(sz) {}    Data run(const Tag &another) const {        if (minx > maxx) return *this;        Data ret;        ret.sum = sum * another.k + sz * another.b;        ret.sz = sz;        if (another.k < 0) {            ret.minx = another.k * maxx + another.b;            ret.maxx = another.k * minx + another.b;        }        else {            ret.maxx = another.k * maxx + another.b;            ret.minx = another.k * minx + another.b;        }        return ret;    }    Data run(const Data &another) const {        Data ret;        if (minx > maxx) return another;        if (another.minx > another.minx) return *this;        ret.sz = sz + another.sz;        ret.sum = sum + another.sum;        ret.minx = Min(minx, another.minx);        ret.maxx = Max(maxx, another.maxx);        return ret;    }};struct Node {    bool inner;    bool is_rev;    Node *ch[4], *fa;    Tag tag_chain, tag_sub;    Data data_chain, data_sub, data_all, my;    void pushdown();    void update();    void add();    void del();    void push();    void pushO();    void pushI();    void splayO();    void splayI();    void rotate(int);    void access(bool=false);    bool is_top_out();    bool is_top_inn();    void makerot();    void push_rev();    void push_tag_chain(Tag);    void push_tag_sub(Tag);} *to[MAXN];int n, m, rt;int input[MAXN][2], w[MAXN];int debug(Node *x){    FOR(i, 1, n) if (x == to[i]) return i;    return 0;}void Node::pushO(){    assert(!inner);    if (!is_top_out()) fa -> pushO();    pushdown();}void Node::pushI(){    //if (!inner) return;    assert(inner);    if (!is_top_inn()) fa -> pushI();    pushdown();}void initialize(){    FOR(i, 1, n) {        to[i] = new Node;        to[i] -> ch[0] = to[i] -> ch[1] =            to[i] -> ch[2] = to[i] -> ch[3] = NULL;        to[i] -> fa = NULL;        to[i] -> inner = false;        to[i] -> is_rev = false;        to[i] -> tag_chain = to[i] -> tag_sub = Tag();        to[i] -> data_chain = to[i] -> data_sub = Data();        to[i] -> my = Data(1, w[i], w[i], w[i]);        to[i] -> data_all =            to[i] -> my.run(to[i] -> data_chain).run(to[i] -> data_sub);    }}void Node::push(){    if (fa) fa -> push(); pushdown();}bool Node::is_top_out(){    return !fa || fa -> ch[0] != this && fa -> ch[1] != this;}bool Node::is_top_inn(){    //printf("%d %d\n", inner, fa);    //printf("%d\n", fa != NULL);    return !fa -> inner;}void Node::add(){    Node *tmp = fa;    while (tmp -> ch[3] != NULL && (tmp -> inner || tmp == fa)) {        tmp -> pushdown();        tmp = tmp -> ch[3];    }    if (tmp != fa) assert(!tmp -> inner);    if (tmp == fa) tmp -> ch[3] = this;    else {        tmp -> fa -> ch[3] = new Node;        Node *&x = tmp -> fa -> ch[3];        x -> inner = true;        x -> is_rev = false;        x -> fa = tmp -> fa;        x -> ch[0] = x -> ch[1] = NULL;        x -> ch[2] = tmp; x -> ch[3] = this;        tmp -> fa = fa = x;        Node *tep = x;        while (tep -> inner) {            tep -> update(); tep = tep -> fa;        }        x -> splayI();    }}void Node::del(){    int t = fa -> ch[2] == this ? 2 : 3;    if (fa -> ch[t] != this) {        assert(fa -> ch[t] == this);    }    if (fa -> inner) {//      Node *tt = fa;        fa -> pushI();        Node *bro = fa -> ch[t ^ 1];        bro -> fa = fa -> fa;        int tt = bro -> fa -> ch[2] == fa ? 2 : 3;        assert(bro -> fa -> ch[tt] == fa);        bro -> fa -> ch[tt] = bro;        Node *tep = bro -> fa;        while (tep -> inner) {            tep -> update(); tep = tep -> fa;        }        if (bro -> fa -> inner)            bro -> fa -> splayI();        delete fa;    }    else {        fa -> pushdown();        fa -> ch[t] = NULL;    }}//不负责update,只负责pushdownvoid Node::access(bool is){    push();    splayO(); pushdown();    if (ch[1] != NULL) ch[1] -> add();    ch[1] = NULL; update();    Node *x = this;    while (x -> fa != NULL) {        Node *tmp = x -> fa;        while (tmp -> inner) tmp = tmp -> fa;        if (!is) x -> del();        else is = false;        //while (tmp -> inner) tmp = tmp -> fa;        tmp -> splayO(); tmp -> pushdown();        if (tmp -> ch[1] != NULL) tmp -> ch[1] -> add();        x -> fa = tmp;        tmp -> ch[1] = x; tmp -> update();        x = tmp;    }}void Node::rotate(int dir){    Node *pa = fa; fa = pa -> fa;    if (fa != NULL) {        int t = (fa -> ch[0] == pa ? 0 :                 (fa -> ch[1] == pa ? 1 : (fa -> ch[2] == pa ? 2 : 3)));        fa -> ch[t] = this;    }    pa -> ch[dir] = ch[dir ^ 1];    if (ch[dir ^ 1] != NULL) ch[dir ^ 1] -> fa = pa;    ch[dir ^ 1] = pa; pa -> fa = this;    pa -> update(); update();}void Node::splayO(){    assert(!inner);    pushO();    while (!is_top_out()) {        int t1 = fa -> ch[0] == this ? 0 : 1;        if (!fa -> is_top_out()) {            int t2 = fa -> fa -> ch[0] == fa ? 0 : 1;            if (t1 == t2) fa -> rotate(t1), rotate(t1);            else rotate(t1), rotate(t2);        }        else rotate(t1);    }}void Node::splayI(){    assert(inner);    pushI();    while (!is_top_inn()) {        int t1 = fa -> ch[2] == this ? 2 : 3;        if (!fa -> is_top_inn()) {            int t2 = fa -> fa -> ch[2] == fa ? 2 : 3;            if (t1 == t2) fa -> rotate(t1), rotate(t1);            else rotate(t1), rotate(t2);        }        else rotate(t1);    }}void Node::push_rev(){    is_rev ^= 1;    std::swap(ch[0], ch[1]);}void Node::push_tag_chain(Tag x){    tag_chain = tag_chain.run(x);    my = my.run(x);    data_chain = data_chain.run(x);    data_all = my.run(data_sub).run(data_chain);}void Node::push_tag_sub(Tag x){    tag_sub = tag_sub.run(x);    //tag_chain = tag_chain.run(x);    //my = my.run(x);    data_sub = data_sub.run(x);    //data_chain = data_chain.run(x);    data_all = my.run(data_sub).run(data_chain);}void Node::update(){    data_sub = Data();    if (ch[0] != NULL) data_sub = data_sub.run(ch[0] -> data_sub);    if (ch[1] != NULL) data_sub = data_sub.run(ch[1] -> data_sub);    if (ch[2] != NULL) data_sub = data_sub.run(ch[2] -> data_all);    if (ch[3] != NULL) data_sub = data_sub.run(ch[3] -> data_all);    data_chain = Data();    if (ch[0] != NULL)        data_chain = data_chain.run(ch[0] -> data_chain).run(ch[0] -> my);    if (ch[1] != NULL)        data_chain = data_chain.run(ch[1] -> data_chain).run(ch[1] -> my);    data_all = my.run(data_sub).run(data_chain);}void Node::pushdown(){    if (is_rev) {        if (ch[0] != NULL) ch[0] -> push_rev();        if (ch[1] != NULL) ch[1] -> push_rev();        is_rev = false;    }    {        Tag &tag = tag_chain;        if (tag.k != 1 || tag.b != 0) {            if (ch[0] != NULL) ch[0] -> push_tag_chain(tag);            if (ch[1] != NULL) ch[1] -> push_tag_chain(tag);            tag = Tag(1, 0);        }    }    {        Tag &tag = tag_sub;        if (tag.k != 1 || tag.b != 0) {            if (ch[0] != NULL) ch[0] -> push_tag_sub(tag);            if (ch[1] != NULL) ch[1] -> push_tag_sub(tag);            if (ch[2] != NULL) {                ch[2] -> push_tag_chain(tag);                ch[2] -> push_tag_sub(tag);            }            if (ch[3] != NULL) {                ch[3] -> push_tag_chain(tag);                ch[3] -> push_tag_sub(tag);            }            tag = Tag(1, 0);        }    }}void Node::makerot(){    access(); splayO(); push_rev();}void link(Node *x, Node *y){    y -> access(); y -> pushdown();    x -> makerot(); x -> fa = y; x -> access(true);}void cut(Node *x, Node *y){    x -> makerot(); y -> access(); y -> splayO();    y -> pushdown(); x -> fa = y -> ch[0] = NULL; y -> update();}Node *find_rot(Node *x){    x -> access(); x -> splayO(); x -> pushdown();    while (x -> ch[0] != NULL) {        x = x -> ch[0]; x -> pushdown();    }    return x;}int main(){    in(n); in(m);    FOR(i, 1, n - 1) {        in(input[i][0]); in(input[i][1]);     }    FOR(i, 1, n) in(w[i]);    initialize();    in(rt);    FOR(i, 1, n - 1) {        link(to[input[i][0]], to[input[i][1]]);    }    FOR(i, 1, m) {        int tp; in(tp);        to[rt] -> makerot();        //FOR(i, 1, n)        //  to[i] -> access();        //to[rt] -> splayO();        //printf("%d\n", to[rt] -> data_all.sz);        if (tp == 0) {            int x, y; in(x); in(y);            to[x] -> access(); to[x] -> splayO();            if (x == rt) {                to[x] -> push_tag_chain(Tag(0, y));                to[x] -> push_tag_sub(Tag(0, y));            }            else {                to[x] -> my = to[x] -> my.run(Tag(0, y));                if (to[x] -> ch[3] != NULL) {                    to[x] -> ch[3] -> push_tag_chain(Tag(0, y));                    to[x] -> ch[3] -> push_tag_sub(Tag(0, y));                }                if (to[x] -> ch[2] != NULL) {                    to[x] -> ch[2] -> push_tag_chain(Tag(0, y));                    to[x] -> ch[2] -> push_tag_sub(Tag(0, y));                }                to[x] -> update();            }        }        else if (tp == 1) {            int x; in(x); rt = x;        }        else if (tp == 2) {            int x, y, z; in(x); in(y); in(z);            to[x] -> makerot(); to[y] -> access(); to[y] -> splayO();            to[y] -> push_tag_chain(Tag(0, z));        }        else if (tp == 3) {            int x; in(x); to[x] -> access();            Data ret = Data();            if (to[x] -> ch[2] != NULL) ret = ret.run(to[x] -> ch[2] -> data_all);            if (to[x] -> ch[3] != NULL) ret = ret.run(to[x] -> ch[3] -> data_all);            ret = ret.run(to[x] -> my);            printf("%d\n", ret.minx);        }        else if (tp == 4) {            int x; in(x); to[x] -> access();            Data ret = Data();            if (to[x] -> ch[2] != NULL) ret = ret.run(to[x] -> ch[2] -> data_all);            if (to[x] -> ch[3] != NULL) ret = ret.run(to[x] -> ch[3] -> data_all);            ret = ret.run(to[x] -> my);            printf("%d\n", ret.maxx);        }        else if (tp == 5) {            int x, y; in(x); in(y);            to[x] -> access(); to[x] -> splayO();            if (x == rt) {                to[x] -> push_tag_chain(Tag(1, y));                to[x] -> push_tag_sub(Tag(1, y));            }            else {                to[x] -> my = to[x] -> my.run(Tag(1, y));                if (to[x] -> ch[2] != NULL) {                    to[x] -> ch[2] -> push_tag_chain(Tag(1, y));                    to[x] -> ch[2] -> push_tag_sub(Tag(1, y));                }                if (to[x] -> ch[3] != NULL) {                    to[x] -> ch[3] -> push_tag_chain(Tag(1, y));                    to[x] -> ch[3] -> push_tag_sub(Tag(1, y));                }                to[x] -> update();            }        }        else if (tp == 6) {            int x, y, z; in(x); in(y); in(z);            to[x] -> makerot(); to[y] -> access(); to[y] -> splayO();            to[y] -> push_tag_chain(Tag(1, z));        }        else if (tp == 7) {            int x, y; in(x); in(y);            to[x] -> makerot(); to[y] -> access(); to[y] -> splayO();            printf("%d\n", to[y] -> my.run(to[y] -> data_chain).minx);        }        else if (tp == 8) {            int x, y; in(x); in(y);            to[x] -> makerot(); to[y] -> access(); to[y] -> splayO();            printf("%d\n", to[y] -> my.run(to[y] -> data_chain).maxx);        }        else if (tp == 9) {            int x, y; in(x); in(y);            to[y] -> access(); to[x] -> access();            to[x] -> splayO(); to[x] -> pushdown();            if (to[x] -> ch[0] == NULL) continue;            else {                to[y] -> access(); to[y] -> splayO();                Node *tmp = to[x];                while (!tmp -> is_top_out()) tmp = tmp -> fa;                if (tmp == to[y]) continue;                to[x] -> access(); to[x] -> splayO(); to[x] -> pushdown();                tmp = to[x] -> ch[0]; tmp -> pushdown();                while (tmp -> ch[1] != NULL) {tmp = tmp -> ch[1]; tmp -> pushdown();}                cut(to[x], tmp); link(to[x], to[y]);            }        }        else if (tp == 10) {            int x, y; in(x); in(y);            to[x] -> makerot(); to[y] -> access(); to[y] -> splayO();            printf("%d\n", to[y] -> my.run(to[y] -> data_chain).sum);        }        else if (tp == 11) {            int x; in(x); to[x] -> access(); //to[x] -> splayO();            Data ret = Data();            if (to[x] -> ch[2] != NULL) ret = ret.run(to[x] -> ch[2] -> data_all);            if (to[x] -> ch[3] != NULL) ret = ret.run(to[x] -> ch[3] -> data_all);            ret = ret.run(to[x] -> my);            printf("%d\n", ret.sum);        }    }    return 0;}