zoukankan      html  css  js  c++  java
  • POJ 3237 Tree

    POJ_3237

        用link-cut-tree或者树链剖分都可以,为了处理negate操作,出了lazy标记外可以做两个标记max、min,在执行negate时,令max=-min、min=-max即可。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 100010
    #define MAXM 200010
    #define INF 0x7fffffff
    int N, q[MAXD], first[MAXD], e, next[MAXM], v[MAXM], w[MAXM], dep[MAXD];
    struct Edge
    {
        int x, y, z;
    }edge[MAXD];
    struct Splay
    {
        int pre, ls, rs, neg, key, max, min;
        bool root;
        void update(); void pushdown(); void zig(int ); void zag(int ); void splay(int );
        void renew()
        {
            root = true;
            pre = ls = rs = 0;
            neg = 0;
        }
    }sp[MAXD];
    int Max(int x, int y)
    {
        return x > y ? x : y;
    }
    int Min(int x, int y)
    {
        return x < y ? x : y;
    }
    void Splay::update()
    {
        max = Max(Max(sp[ls].max, sp[rs].max), key);
        min = Min(Min(sp[ls].min, sp[rs].min), key);
    }
    void makeneg(int cur)
    {
        if(cur != 0)
        {
            sp[cur].neg ^= 1, sp[cur].key = -sp[cur].key;
            int t = sp[cur].max;
            sp[cur].max = -sp[cur].min, sp[cur].min = -t;
        }
    }
    void Splay::pushdown()
    {
        if(neg)
        {
            makeneg(ls), makeneg(rs);
            neg = 0;
        }
    }
    void Splay::zig(int x)
    {
        int y = rs, fa = pre;
        pushdown(), sp[y].pushdown();
        rs = sp[y].ls, sp[rs].pre = x;
        sp[y].ls = x, pre = y;
        sp[y].pre = fa;
        if(root)
            root = false, sp[y].root = true;
        else
            sp[fa].rs == x ? sp[fa].rs = y : sp[fa].ls = y;
        update();
    }
    void Splay::zag(int x)
    {
        int y = ls, fa = pre;
        pushdown(), sp[y].pushdown();
        ls = sp[y].rs, sp[ls].pre = x;
        sp[y].rs = x, pre = y;
        sp[y].pre = fa;
        if(root)
            root = false, sp[y].root = true;
        else
            sp[fa].rs == x ? sp[fa].rs = y : sp[fa].ls = y;
        update();
    }
    void Splay::splay(int x)
    {
        int y, z;
        for(pushdown(); !root;)
        {
            y = pre;
            if(sp[y].root)
                sp[y].rs == x ? sp[y].zig(y) : sp[y].zag(y);
            else
            {
                z = sp[y].pre;
                if(sp[z].rs == y)
                {
                    if(sp[y].rs == x)
                        sp[z].zig(z), sp[y].zig(y);
                    else
                        sp[y].zag(y), sp[z].zig(z);
                }
                else
                {
                    if(sp[y].ls == x)
                        sp[z].zag(z), sp[y].zag(y);
                    else
                        sp[y].zig(y), sp[z].zag(z);
                }
            }
        }
        update();
    }
    void add(int x, int y, int z)
    {
        v[e] = y, w[e] = z;
        next[e] = first[x], first[x] = e ++;
    }
    void prepare()
    {
        int i, j, x, rear = 0;
        sp[0].max = -INF, sp[0].min = INF;
        q[rear ++] = 1;
        sp[1].renew(), dep[1] = 1;
        for(i = 0; i < rear; i ++)
        {
            x = q[i];
            for(j = first[x]; j != -1; j = next[j])
                if(v[j] != sp[x].pre)
                {
                    sp[v[j]].renew(), sp[v[j]].pre = x, dep[v[j]] = dep[x] + 1;
                    sp[v[j]].key = sp[v[j]].max = sp[v[j]].min = w[j];
                    q[rear ++] = v[j];
                }
        }
    }
    void Swap(int &x, int &y)
    {
        int t;
        t = x, x = y, y = t;
    }
    void init()
    {
        int i;
        memset(first, -1, sizeof(first));
        e = 0;
        scanf("%d", &N);
        for(i = 1; i < N; i ++)
        {
            scanf("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].z);
            add(edge[i].x, edge[i].y, edge[i].z), add(edge[i].y, edge[i].x, edge[i].z);
        }
        prepare();
        for(i = 1; i < N; i ++)
            if(dep[edge[i].x] > dep[edge[i].y])
                Swap(edge[i].x, edge[i].y);
    }
    void access(int x)
    {
        int fx;
        for(fx = x, x = 0; fx != 0; x = fx, fx = sp[x].pre)
        {
            sp[fx].splay(fx);
            sp[sp[fx].rs].root = true;
            sp[fx].rs = x, sp[x].root = false;
            sp[fx].update();
        }
    }
    void Change(int x, int y)
    {
        sp[x].splay(x);
        sp[x].key = y;
        sp[x].update();
    }
    void Negate(int x, int y)
    {
        int fy;
        access(x);
        for(fy = y, y = 0; fy != 0; y = fy, fy = sp[y].pre)
        {
            sp[fy].splay(fy);
            if(sp[fy].pre == 0)
                makeneg(sp[fy].rs), makeneg(y);
            sp[sp[fy].rs].root = true;
            sp[fy].rs = y, sp[y].root = false;
            sp[fy].update();
        }
    }
    void Query(int x, int y)
    {
        int fy;
        access(x);
        for(fy = y, y = 0; fy != 0; y = fy, fy = sp[y].pre)
        {
            sp[fy].splay(fy);
            if(sp[fy].pre == 0)
                printf("%d\n", Max(sp[sp[fy].rs].max, sp[y].max));
            sp[sp[fy].rs].root = true;
            sp[fy].rs = y, sp[y].root = false;
            sp[fy].update();
        }
    }
    void solve()
    {
        int x, y;
        char op[10];
        for(;;)
        {
            scanf("%s", op);
            if(op[0] == 'D')
                break;
            scanf("%d%d", &x, &y);
            if(op[0] == 'C')
                Change(edge[x].y, y);
            else if(op[0] == 'N')
                Negate(x, y);
            else
                Query(x, y);
        }
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t --)
        {
            init();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    SonarQube 之 权限模板配置
    window jenkins + sonarqube + sonar-scanner 最佳实践
    到某个指定的页面不可以后退
    php里面判断是pc还是手机
    爱奇艺视频引入
    给电脑安装字体
    应用宝下线
    ps 如何的复制想要的东西,以及修改
    实现倒计时的效果(3秒倒计时)
    数据库里的数据被删除,依然想按照顺序往下递增的解决办法
  • 原文地址:https://www.cnblogs.com/staginner/p/2551758.html
Copyright © 2011-2022 走看看