zoukankan      html  css  js  c++  java
  • SPOJ 6779 Can you answer these queries VII

    SPOJ_6779

        这个题目和GSS1的思想是一样的,只不过由于变成了树,所以可以先用树链剖分先将树划分成若干棵线段树再进行求解。

        另外我的代码写得确实比较挫,推荐一份效率比较高的用动态树写的代码:http://ideone.com/wA3Pr

    View Code // 轻重边树链剖分
    #include<stdio.h>
    #include<string.h>
    #define MAXD 100010
    #define MAXM 200010
    #define INF 0x3f3f3f3f
    int N, a[MAXD], mc[4 * MAXD], lc[4 * MAXD], rc[4 * MAXD], to[4 * MAXD], sum[4 * MAXD];
    int first[MAXD], e, next[MAXM], v[MAXM];
    int q[MAXD], fa[MAXD], dep[MAXD], size[MAXD], son[MAXD], top[MAXD], w[MAXD], cnt;
    void Swap(int &x, int &y)
    {
        int t;
        t = x, x = y, y = t;
    }
    int Max(int x, int y)
    {
        return x > y ? x : y;
    }
    void add(int x, int y)
    {
        v[e] = y;
        next[e] = first[x], first[x] = e ++;
    }
    void pushdown(int cur, int x, int y)
    {
        if(to[cur] != INF)
        {
            int mid = (x + y) >> 1, ls = cur << 1, rs = cur << 1 | 1;
            to[ls] = to[rs] = to[cur];
            sum[ls] = (mid - x + 1) * to[cur], sum[rs] = (y - mid) * to[cur];
            mc[ls] = lc[ls] = rc[ls] = to[cur] > 0 ? sum[ls] : to[cur];
            mc[rs] = lc[rs] = rc[rs] = to[cur] > 0 ? sum[rs] : to[cur];
            to[cur] = INF;
        }
    }
    void update(int cur, int x, int y)
    {
        int mid = (x + y) >> 1, ls = cur << 1, rs = cur << 1 | 1;
        sum[cur] = sum[ls] + sum[rs];
        mc[cur] = Max(Max(mc[ls], mc[rs]), rc[ls] + lc[rs]);
        lc[cur] = Max(lc[ls], sum[ls] + lc[rs]);
        rc[cur] = Max(rc[rs], sum[rs] + rc[ls]);
    }
    void refresh(int cur, int x, int y, int s, int t, int v)
    {
        int mid = (x + y) >> 1, ls = cur << 1, rs = cur << 1 | 1;
        if(x >= s && y <= t)
        {
            to[cur] = v;
            sum[cur] = v * (y - x + 1);
            mc[cur] = lc[cur] = rc[cur] = v > 0 ? sum[cur] : v;
            return ;
        }
        pushdown(cur, x, y);
        if(mid >= s)
            refresh(ls, x, mid, s, t, v);
        if(mid + 1 <= t)
            refresh(rs, mid + 1, y, s, t, v);
        update(cur, x, y);
    }
    int Search(int cur, int x, int y, int s, int t, int flag, int &ans, int &ts, int &tc, int tflag)
    {
        int mid = (x + y) >> 1, ls = cur << 1, rs = cur << 1 | 1;
        if(x >= s && y <= t)
        {
            ans = Max(ans, mc[cur]);
            tc = Max(tc, ts + (tflag == 0 ? lc[cur] : rc[cur]));
            ts += sum[cur];
            return flag == 0 ? lc[cur] : rc[cur];
        }
        pushdown(cur, x, y);
        if(mid >= t)
            return Search(ls, x, mid, s, t, 0, ans, ts, tc, tflag);
        else if(mid + 1 <= s)
            return Search(rs, mid + 1, y, s, t, 1, ans, ts, tc, tflag);
        else
        {
            int ln, rn;
            if(tflag == 0)
                ln = Search(ls, x, mid, s, t, 1, ans, ts, tc, tflag), rn = Search(rs, mid + 1, y, s, t, 0, ans, ts, tc, tflag);
            else
                rn = Search(rs, mid + 1, y, s, t, 0, ans, ts, tc, tflag), ln = Search(ls, x, mid, s, t, 1, ans, ts, tc, tflag);
            ans = Max(ans, ln + rn);
            if(flag == 0)
                return Max(lc[ls], sum[ls] + rn);
            else
                return Max(rc[rs], sum[rs] + ln);
        }
    }
    void prepare()
    {
        int i, j, k, x, rear = 0;
        q[rear ++] = 1;
        dep[1] = 1, fa[1] = 0;
        for(i = 0; i < rear; i ++)
        {
            x = q[i];
            for(j = first[x]; j != -1; j = next[j])
                if(v[j] != fa[x])
                {
                    dep[v[j]] = dep[x] + 1;
                    fa[v[j]] = x;
                    q[rear ++] = v[j];
                }
        }
        size[0] = 0;
        for(i = rear - 1; i >= 0; i --)
        {
            x = q[i];
            son[x] = 0, size[x] = 1;
            for(j = first[x]; j != -1; j = next[j])
                if(v[j] != fa[x])
                {
                    size[x] += size[v[j]];
                    if(size[v[j]] > size[son[x]])
                        son[x] = v[j];
                }
        }
        memset(top, 0, sizeof(top));
        cnt = 0;
        for(i = 0; i < rear; i ++)
        {
            x = q[i];
            if(!top[x])
            {
                j = x;
                while(j != 0)
                    top[j] = x, w[j] = ++ cnt, j = son[j];
            }
        }
    }
    void init()
    {
        int i, j, k, x, y;
        for(i = 1; i <= N; i ++)
            scanf("%d", &a[i]);
        memset(first, -1, sizeof(first));
        e = 0;
        for(i = 1; i < N; i ++)
        {
            scanf("%d%d", &x, &y);
            add(x, y), add(y, x);
        }
        prepare();
        memset(to, 0x3f, sizeof(to));
        for(i = 1; i <= N; i ++)
            refresh(1, 1, N, w[i], w[i], a[i]);
    }
    void query(int x, int y)
    {
        int fx = top[x], fy = top[y], cx, cy, ans, ts, tc;
        cx = cy = ans = 0;
        while(fx != fy)
        {
            if(dep[fx] > dep[fy])
                Swap(fx, fy), Swap(x, y), Swap(cx, cy);
            ts = tc = 0;
            Search(1, 1, N, w[fy], w[y], 0, ans, ts, tc, 1);
            ans = Max(ans, tc + cy);
            ts = tc = 0;
            Search(1, 1, N, w[fy], w[y], 0, ans, ts, tc, 0);
            cy = Max(ts + cy, tc);
            y = fa[fy], fy = top[y];
        }
        if(dep[x] > dep[y])
            Swap(x, y), Swap(cx, cy);
        ts = tc = 0;
        Search(1, 1, N, w[x], w[y], 0, ans, ts, tc, 0);
        ans = Max(ans, tc + cx);
        ts = tc = 0;
        Search(1, 1, N, w[x], w[y], 0, ans, ts, tc, 1);
        ans = Max(ans, tc + cy);
        ans = Max(ans, cx + ts + cy);
        printf("%d\n", ans);
    }
    void change(int x, int y, int v)
    {
        int fx = top[x], fy = top[y];
        while(fx != fy)
        {
            if(dep[fx] > dep[fy])
                Swap(x, y), Swap(fx, fy);
            refresh(1, 1, N, w[fy], w[y], v);
            y = fa[fy], fy = top[y];
        }
        if(dep[x] > dep[y])
            Swap(x, y);
        refresh(1, 1, N, w[x], w[y], v);
    }
    void solve()
    {
        int i, j, a, b, c, op, q;
        scanf("%d", &q);
        for(i = 0; i < q; i ++)
        {
            scanf("%d%d%d", &op, &a, &b);
            if(op == 1)
                query(a, b);
            else
            {
                scanf("%d", &c);
                change(a, b, c);
            }
        }
    }
    int main()
    {
        while(scanf("%d", &N) == 1)
        {
            init();
            solve();
        }
        return 0;
    }

        就这个题目而言,我写的link-cut-tree的代码要比树链剖分快一些,大概有这么两个原因:①树链剖分或者线段树更新的部分我写得太挫了;②用树链剖分写的话,在求解最大连续和的时候本身就比较麻烦,而link-cut-tree求解的时候则很方便。

    View Code // link-cut-tree
  • 相关阅读:
    linux eclipse cdt make error 127
    centos 安装网络错误
    c++ string 结束符‘00’
    北京市工资交税情况
    gprof参数说明及常见错误
    【转】Eclipse Plugin 在 Console上打印出message
    C++做client Java做客户端传送数据
    word统计章节字数
    【转】Profiling application LLC cache misses under Linux using Perf Events
    【转】eclipse插件开发,调试运行,导出与安装
  • 原文地址:https://www.cnblogs.com/staginner/p/2544305.html
Copyright © 2011-2022 走看看