[BZOJ 1146] [CTSC2008]网络管理Network

来源:互联网 发布:广联达软件价格 编辑:程序博客网 时间:2024/05/16 14:35

http://www.lydsy.com/JudgeOnline/problem.php?id=1146

树巨结垢限时训练系列。
选择了 二分 树剖 线段树 Treap 的写法。
1小时写完 15分钟调好…..
感觉写的已经比较漂亮了,可以作为树上单点修改 K 大的一份模版

#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <vector>#define rep(i, x, y) for (int i = (x), _ = (y); i <= _; ++i)#define down(i, x, y) for (int i = (x), _ = (y); i >= _; --i)#define x first#define y second#define LX_JUDGEusing namespace std;typedef long long LL;template<typename T> inline void up_max(T & x, T y) { x < y ? x = y : 0; }template<typename T> inline void up_min(T & x, T y) { x > y ? x = y : 0; }template<typename T>inline void read(T & x){    char c;    while ((c = getchar()) < '0' || c > '9') ;    for (x = c - '0'; (c = getchar()) >= '0' && c <= '9'; x = x * 10 + c - '0') ;}const int N = 8e4 + 10;namespace Treap{    struct node    {        node * ch[2];        int val, size, r;        inline void push_up()        {            size = (ch[0] ? ch[0]->size : 0) + (ch[1] ? ch[1]->size : 0) + 1;        }    } pool_node[N * 20], *pool_top = pool_node;    node * root = 0;    void rotate(node *&o, int d)    {        node * u = o->ch[d];        o->ch[d] = u->ch[d ^ 1];        u->ch[d ^ 1] = o;        o->push_up();        u->push_up();        o = u;    }    void insert(node *& o, node * u)    {        if (!o)        {            o = u;            o->ch[0] = o->ch[1] = 0;            o->size = 1;            return ;        }        int d = o->val < u->val;        ++o->size;        insert(o->ch[d], u);        if (o->ch[d]->r > o->r)            rotate(o, d);    }    node * recent;    void remove(node *& o, int val)    {        if (o->val == val)        {            if (!o->ch[0])            {                recent = o;                o = o->ch[1];            }            else if (!o->ch[1])            {                recent = o;                o = o->ch[0];            }            else             {                int d = o->ch[1]->r > o->ch[0]->r;                rotate(o, d);                --o->size;                remove(o->ch[d ^ 1], val);            }        }        else         {            int d = o->val < val;            --o->size;            remove(o->ch[d], val);        }    }    void modify(node *& R, int val, int to)    {        remove(R, val);        recent->val = to;        insert(R, recent);    }    node * build(int * a, int n)    {        static node * stk[N];        static int top = 0;        rep(i, 0, n - 1)        {            node * o = ++pool_top, *last = 0;            o->val = a[i];            o->r = rand();            while (top && stk[top]->r < o->r)                stk[top]->push_up(), last = stk[top--];            if (top)                stk[top]->ch[1] = o;            o->ch[0] = last;            stk[++top] = o;        }        while (top)             stk[top--]->push_up();        return stk[1];    }    int getRank(node *o, int val)    {        int ret = 0;        while (o)        {            int d = o->val < val;            if (!d)                ret += (o->ch[1] ? o->ch[1]->size : 0) + 1;            o = o->ch[d];        }        return ret;    }    int query(const vector<node * > & q, int K)    {        int l = 1, r = 1e8;        while (l <= r)        {            int mid = (l + r) >> 1, tmp = 0;            rep (i, 0, q.size() - 1)                tmp += getRank(q[i], mid);            tmp >= K ? l = mid + 1 : r = mid - 1;        }        return r;    }}int mem_tmp[N], mem[N];namespace SegmentTree{    struct node    {        node * ch[2];        int l, r;        Treap::node * root;    };    node * newnode()    {        static node pool_node[N * 2], * pool_top = pool_node;        return ++pool_top;    }    void build(node *&o, int l, int r)    {        o = newnode();        o->l = l, o->r = r;        if (l == r)        {            o->root = Treap::build(mem + l, 1);            return ;        }        int mid = (l + r) >> 1;        build(o->ch[0], l, mid);        build(o->ch[1], mid + 1, r);        int tl = l, tr = mid + 1;        for (int i = l; i <= r; ++i)        {            if (tr > r || (tl <= mid && mem[tl] < mem[tr]))                mem_tmp[i] = mem[tl++];            else                 mem_tmp[i] = mem[tr++];        }        memcpy(mem + l, mem_tmp + l, sizeof(int) * (r - l + 1));        o->root = Treap::build(mem + l, r - l + 1);    }    void split(node *o, int l, int r, vector<Treap::node * > & q)    {        if (l <= o->l && o->r <= r)        {            q.push_back(o->root);            return ;        }        int mid = (o->l + o->r) >> 1;        if (mid >= r)            split(o->ch[0], l, r, q);        else if (mid < l)            split(o->ch[1], l, r, q);        else             split(o->ch[0], l, r, q), split(o->ch[1], l, r, q);    }    int modify(node *o, int pos, int val)    {        if (o->l == o->r)        {            int ret = o->root->val;            Treap::modify(o->root, ret, val);            return ret;        }        int ret = modify(o->ch[((o->l + o->r) >> 1) < pos], pos, val);        Treap::modify(o->root, ret, val);        return ret;    }}SegmentTree::node * H[N];struct edge{    int to;    edge *n;} pool_edge[N * 2], *head[N], *cur = pool_edge;inline void addEdge(int x, int y){    cur->to = y, cur->n = head[x], head[x] = cur++;    cur->to = x, cur->n = head[y], head[y] = cur++;}struct treenode{    int size, Hson, deep, fa, top, dfn;}t[N];void init_dfs(int x){    t[x].size = 1;    for (edge *p = head[x]; p; p = p->n)     {        int to = p->to;        if (t[x].fa == to)            continue ;        t[to].fa = x;        t[to].deep = t[x].deep + 1;        init_dfs(to);        t[x].size += t[to].size;        if (t[to].size > t[t[x].Hson].size)            t[x].Hson = to;    }}int ival[N], tim;void calc_dfs(int x, int tt){    t[x].dfn = ++tim;    t[x].top = tt;    mem[tim] = ival[x];    if (t[x].Hson)    {        calc_dfs(t[x].Hson, tt);        for (edge *p = head[x]; p; p = p->n) if (t[x].fa != p->to && t[x].Hson != p->to)            calc_dfs(p->to, p->to);    }    else         SegmentTree::build(H[t[x].top], t[t[x].top].dfn, t[x].dfn);}int solve(int x, int y, int K){    using SegmentTree::split;    static vector<Treap::node *> Q;    Q.clear();    int cnt = 0;    while (t[x].top != t[y].top)    {        if (t[t[x].top].deep < t[t[y].top].deep)            swap(x, y);        split(H[t[x].top], t[t[x].top].dfn, t[x].dfn, Q);        cnt += t[x].dfn - t[t[x].top].dfn + 1;        x = t[t[x].top].fa;    }    if (t[x].deep > t[y].deep)        swap(x, y);    cnt += t[y].dfn - t[x].dfn + 1;    split(H[t[x].top], t[x].dfn, t[y].dfn, Q);    return cnt >= K ? Treap::query(Q, K) : -1;}int main(){#ifdef LX_JUDGE    freopen("in.txt", "r", stdin);#endif    int n, m;    read(n), read(m);    rep (i, 1, n)        read(ival[i]);    for (int i = 1, x, y; i < n; ++i)    {        read(x), read(y);        addEdge(x, y);    }    init_dfs(1);    calc_dfs(1, 1);    int opt, x, y;    while (m--)    {        read(opt);        read(x), read(y);        if (opt == 0)            SegmentTree::modify(H[t[x].top], t[x].dfn, y);        else         {            x = solve(x, y, opt);            x > 0 ? printf("%d\n", x) : puts("invalid request!");        }    }    return 0;}
0 0