[bzoj3153] sone1 AC纪念

2 篇文章 0 订阅

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,只负责pushdown
void 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;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值