zoukankan      html  css  js  c++  java
  • 1103 POI2007 大都市meg

        树链剖分水过,单点修改,树状数组即可。

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define N 250100
    using namespace std;
    
    int n, m, nowplace = 0;
    int p[N] = {0}, next[N], v[N], bnum = 0;
    int son[N] = {0}, fa[N], w[N], top[N], deep[N] = {0}, num[N];
    int t[N] = {0};
    
    int lowbit(int x) { return x & -x; }
    
    void dfs_1(int now, int fat)
    {
        int k = p[now]; num[now] = 1; int maxson = 0;
        fa[now] = fat; deep[now] = deep[fat] + 1;
        while (k)
        {
            dfs_1(v[k], now);
            if (num[v[k]] > maxson)
            {
                maxson = num[v[k]];
                son[now] = v[k];
            }
            num[now] += num[v[k]];
            k = next[k];
        }
    }
    
    void dfs_2(int now, int nowtop)
    {
        int k = p[now]; w[now] = ++nowplace; top[now] = nowtop;
        if (son[now]) dfs_2(son[now], nowtop);
        while (k)
        {
            if (v[k] != son[now])
                dfs_2(v[k], v[k]);
            k = next[k];
        }
    }
    
    void add(int now, int addnum)
    {
        while (now <= n)
        {
            t[now] += addnum;
            now += lowbit(now);
        }
        return;
    }
    
    int task(int now)
    {
        int ans = 0;
        while (now)
        {
            ans += t[now];
            now -= lowbit(now);
        }
        return ans;
    }
    
    int ask(int u, int v)
    {
        int f1 = top[u], f2 = top[v];
        if (deep[f1] < deep[f2]) { swap(f1, f2); swap(u, v); }
        if (f1 == f2) return task(max(w[u], w[v])) - task(min(w[u], w[v])-1);
        else
        {
            int ans = 0;
            ans = task(w[u]) - task(w[f1]-1); // 搞清先后
            ans += ask(fa[f1], v);
            return ans;
        }
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i < n; ++i)
        {
            int x, y; scanf("%d%d", &x, &y);
            if (x > y) swap(x, y);
            bnum++; next[bnum] = p[x]; p[x] = bnum; v[bnum] = y;
        }
        dfs_1(1, 0); dfs_2(1, 1);
        for (int i = 2; i <= n; ++i) add(w[i], 1);
        scanf("%d", &m); m = m+n-1;
        for (int i = 1; i <= m; ++i)
        {
            char s[2]; scanf("%s", s);
            if (s[0] == 'A')
            {
                int x, y; scanf("%d%d", &x, &y);
                if (x > y) swap(x, y);
                add(w[y], -1);
            }
            else
            {
                int x; scanf("%d", &x);
                printf("%d
    ", ask(1, x));
            }
        }
        return 0;
    }

    还有DFS序做法,其实就是求点到根的路径权值和,样例的DFS序 为 1 4 5 5 4 3 3 2 2 1

    我们把入序的地方+1 出序的地方-1, 查询的时候求入序的前缀和 - 1 就OK了(因为要减去多出来的1节点)

    修改的时候入序和出序都改为0

    上代码:

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define N 250010
    using namespace std;
    
    int n, m, nowplace = 0;
    int p[N] = {0}, next[N], v[N], bnum = 0;
    int t[N*2] = {0};
    int first[N], second[N];
    
    int lowbit(int x) { return x & -x; }
    
    void add(int now, int addnum)
    {
        while (now <= 2*n)
        {
            t[now] += addnum;
            now += lowbit(now);
        }
    }
    
    void dfs(int now)
    {
        int k = p[now]; add(++nowplace, 1);
        first[now] = nowplace;
        while (k)
        {
            dfs(v[k]);
            k = next[k];
        }
        add(++nowplace, -1);
        second[now] = nowplace;
    }
    
    int ask(int now)
    {
        int ans = 0;
        while (now)
        {
            ans += t[now];
            now -= lowbit(now);
        }
        return ans;
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i < n; ++i)
        {
            int x, y; scanf("%d%d", &x, &y);
            if (x > y) swap(x, y);
            bnum++; next[bnum] = p[x]; p[x] = bnum; v[bnum] = y;
        }
        dfs(1);
        scanf("%d", &m); m = m+n-1;
        for (int i = 1; i <= m; ++i)
        {
            char s[2]; scanf("%s", s);
            if (s[0] == 'A')
            {
                int x, y; scanf("%d%d", &x, &y);
                if (x < y) swap(x, y);
                add(first[x], -1);
                add(second[x], 1);
            }
            else
            {
                int x; scanf("%d", &x);
                printf("%d
    ", ask(first[x])-1);
            }
        }
        return 0;
    }
  • 相关阅读:
    eclipse下c/cpp " undefined reference to " or "launch failed binary not found"问题
    blockdev 设置文件预读大小
    宝宝语录
    CentOS修改主机名(hostname)
    subprocess报No such file or directory
    用ldap方式访问AD域的的错误解释
    英特尔的VTd技术是什么?
    This virtual machine requires the VMware keyboard support driver which is not installed
    Linux内核的文件预读详细详解
    UNP总结 Chapter 26~29 线程、IP选项、原始套接字、数据链路访问
  • 原文地址:https://www.cnblogs.com/handsomeJian/p/3997973.html
Copyright © 2011-2022 走看看