zoukankan      html  css  js  c++  java
  • SPOJ COT2

    COT2 - Count on a tree II

    You are given a tree with N nodes. The tree nodes are numbered from 1 to N. Each node has an integer weight.

    We will ask you to perform the following operation:

    • u v : ask for how many different integers that represent the weight of nodes there are on the path from u to v.

    Input

    In the first line there are two integers N and M. (N <= 40000, M <= 100000)

    In the second line there are N integers. The i-th integer denotes the weight of the i-th node.

    In the next N-1 lines, each line contains two integers u v, which describes an edge (uv).

    In the next M lines, each line contains two integers u v, which means an operation asking for how many different integers that represent the weight of nodes there are on the path from u to v.

    Output

    For each operation, print its result.

    Example

    Input:
    8 2
    105 2 9 3 8 5 7 7
    1 2
    1 3
    1 4
    3 5
    3 6
    3 7
    4 8
    2 5
    7 8
    Output:
    4
    4

     

    题目链接:SPOJ COT2

    一开始不太会,看着这个人的教程写的:树上莫队,然而还是有几个地方不是很懂而且他的简洁代码跟文中的一些变量名对不上号……,但至少没百度搜到的某些题解代码写的丑

    他的主要做法就是把树用稍微修改的DFS序变成序列,然后根据两种不同的情况进行判断,并且过程中要算上LCA的贡献,代码虽然写出来了但是感觉跟文中的方法有一点出入,有待理解

    最后的LCA判断实际上是多出来的一个点,要还原回去,否则指针是在区间移动的只管辖区间,这个多出来的点会造成错误的影响

    代码:

    #include <stdio.h>
    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    #define CLR(arr,val) memset(arr,val,sizeof(arr))
    #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
    typedef pair<int, int> pii;
    typedef long long LL;
    const double PI = acos(-1.0);
    const int N = 40010;
    const int M = 200010;
    struct edge
    {
        int to, nxt;
        edge() {}
        edge(int _to, int _nxt): to(_to), nxt(_nxt) {}
    };
    struct query
    {
        int u, v;
        int lca, x;
        int id, l, r, b;
        bool operator<(const query &rhs)const
        {
            if (b != rhs.b)
                return b < rhs.b;
            return r < rhs.r;
        }
    };
    edge E[N << 1];
    query Q[M];
    int head[N], tot;
    
    int arr[N];//values in nodes
    int ver[N << 1], F[N], D[N << 1], dp[N << 1][18], ts; //for LCA
    int ST[N << 1], EN[N << 1], A[N << 1], sz, unit; //for Mo's algo
    
    vector<int>vec;
    int ans[M], cnt[N];
    int cnode[N];
    
    void init()
    {
        CLR(head, -1);
        tot = 0;
        ts = 0;
        sz = 0;
        vis.reset();
        vec.clear();
        CLR(ans, 0);
        CLR(cnt, 0);
        CLR(cnode, 0);
    }
    inline void add(int s, int t)
    {
        E[tot] = edge(t, head[s]);
        head[s] = tot++;
    }
    void dfs(int u, int pre, int d)
    {
        ver[++ts] = u;
        D[ts] = d;
        F[u] = ts;
    
        ST[u] = ++sz;
        A[sz] = u;
    
        for (int i = head[u]; ~i; i = E[i].nxt)
        {
            int v = E[i].to;
            if (v != pre)
            {
                dfs(v, u, d + 1);
    
                ver[++ts] = u;
                D[ts] = d;
            }
        }
    
        EN[u] = ++sz;
        A[sz] = u;
    }
    void RMQ_init(int l, int r)
    {
        int i, j;
        for (i = l; i <= r; ++i)
            dp[i][0] = i;
        for (j = 1; l + (1 << j) - 1 <= r; ++j)
        {
            for (i = l; i + (1 << j) - 1 <= r; ++i)
            {
                int a = dp[i][j - 1], b = dp[i + (1 << (j - 1))][j - 1];
                dp[i][j] = D[a] < D[b] ? a : b;
            }
        }
    }
    int LCA(int u, int v)
    {
        int l = F[u], r = F[v];
        if (l > r)
            swap(l, r);
        int k = log2(r - l + 1);
        int a = dp[l][k], b = dp[r - (1 << k) + 1][k];
        return D[a] < D[b] ? ver[a] : ver[b];
    }
    inline void Add(const int &u,int &Ans)
    {
        ++cnode[u];
        if (cnode[u] == 1)
        {
            if (++cnt[arr[u]] == 1)
                ++Ans;
        }
        else if (cnode[u] == 2)
        {
            if (--cnt[arr[u]] == 0)
                --Ans;
        }
    }
    inline void Del(const int &u, int &Ans)
    {
        --cnode[u];
        if (cnode[u] == 0)
        {
            if (--cnt[arr[u]] == 0)
                --Ans;
        }
        else if (cnode[u] == 1)
        {
            if (++cnt[arr[u]] == 1)
                ++Ans;
        }
    }
    int main(void)
    {
        int n, m, i;
        while (~scanf("%d%d", &n, &m))
        {
            init();
            for (i = 1; i <= n; ++i)
            {
                scanf("%d", &arr[i]);
                vec.push_back(arr[i]);
            }
    
            sort(vec.begin(), vec.end());
            vec.erase(unique(vec.begin(), vec.end()), vec.end());
            for (i = 1; i <= n; ++i)
                arr[i] = lower_bound(vec.begin(), vec.end(), arr[i]) - vec.begin() + 1;
    
            for (i = 1; i < n; ++i)
            {
                int u, v;
                scanf("%d%d", &u, &v);
                add(u, v);
                add(v, u);
            }
            dfs(1, -1, 0);
            unit = sqrt(sz);
            RMQ_init(1, ts);
            for (i = 0; i < m; ++i)
            {
                scanf("%d%d", &Q[i].u, &Q[i].v);
                Q[i].id = i;
                Q[i].lca = LCA(Q[i].u, Q[i].v);
    
                if (ST[Q[i].u] > ST[Q[i].v])
                    swap(Q[i].u, Q[i].v);
                if (Q[i].lca == Q[i].u)
                {
                    Q[i].l = ST[Q[i].u];
                    Q[i].r = ST[Q[i].v];
                    Q[i].x = 0;
                }
                else
                {
                    Q[i].l = EN[Q[i].u];
                    Q[i].r = ST[Q[i].v];
                    Q[i].x = 1;
                }
                Q[i].b = Q[i].l / unit;
            }
            sort(Q, Q + m);
            int L = Q[0].l, R = L - 1;
            int Ans = 0;
            for (i = 0; i < m; ++i)
            {
                while (L > Q[i].l)
                    Add(A[--L], Ans);
    
                while (L < Q[i].l)
                    Del(A[L++], Ans);
    
                while (R > Q[i].r)
                    Del(A[R--], Ans);
    
                while (R < Q[i].r)
                    Add(A[++R], Ans);
    
                if (Q[i].x)
                    Add(Q[i].lca, Ans);
    
                ans[Q[i].id] = Ans;
    
                if (Q[i].x)
                    Del(Q[i].lca, Ans);
            }
            for (i = 0; i < m; ++i)
                printf("%d
    ", ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    Windows netstat 查看端口、进程占用
    nginx开启gzip
    linux查看内存
    linux查看进程、端口
    linux查看磁盘信息
    vmware克隆一台机器后修改etho
    java对象访问
    学生基本信息管理
    作业09-异常
    博客作业06--图
  • 原文地址:https://www.cnblogs.com/Blackops/p/6411563.html
Copyright © 2011-2022 走看看