Cattle-off practice match 47 DongDong number of colors (Mo teams algorithm)

Links: https://ac.nowcoder.com/acm/contest/904/E
Source: Cattle-off network

DongDong number of colors
Time limit: C / C ++ 1 second, other languages 2 seconds
to space constraints: C / C ++ 524288K, other languages 1048576K
64bit IO the Format:% LLD
subject description
DongDong is like the number of colors of the girls, she has mastered in operation of the sequence number of colors, and now she began to learn how the number of colors in the trees, now given a n points, n-1 edges of the tree (root depending shop No. 1), each point has a color, Always ask how many different colors x subtree rooted there, dongDong easily solve this problem, but she was trying to quiz you will be programming.

Input Description:
The first line of two integers n, m

The second row of n integer representing the color of each point

Next, n-1 lines each u, v, indicates the presence of a two-way from the edge of u to v (final pattern is guarantee tree)

2 <= n <= 100000,1 < = m, color <= n,
output Description:
Total m rows: row output a corresponding answer each inquiry
Example 1
input
copy
. 4. 3
1. 3 1 2
1 2
2. 3
1. 4
1
2
4
output
copy
. 3
2
. 1

Ideas:
we know the root of the subtree of a node in the tree dfs sequence is a continuous range, and the length is sub-tree size range, so we can maintain the time dfs

1 to i subtree rooted at the node size

2, dfs sequence in which the i-th node.

3, the position of the i-th node in the sequence of dfs.

Then we can put the problem into a problem common range of inquiries, we can use off-line algorithm Mo teams do.

See details Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int* p);
const int maxn = 100010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
ll ans[maxn];
ll Ans=0ll;
int l=0;
int r=0;
struct node
{
    int l,r,id;
}a[maxn];
int pos[maxn];
int n,m;
int len;
bool cmp(node aa,node bb)
{
    if(pos[aa.l]==pos[bb.l])
    {
        return aa.r<bb.r;
    }else
    {
        return pos[aa.l]<pos[bb.l];
    }
}
int col[maxn];
int flag[maxn];
int wid[maxn];
void add(int x)
{
    if(!flag[col[wid[x]]])
    {
        Ans++;
    }
    flag[col[wid[x]]]++;
}
void del(int x)
{
    if(1==flag[col[wid[x]]])
    {
        Ans--;
    }
    flag[col[wid[x]]]--;
}
std::vector<int> son[maxn];
int S[maxn];
int tot=1;
int info[maxn];
void dfs(int x,int pre)
{
    S[x]=1ll;
    info[x]=tot;
    wid[tot++]=x; // 保存dfs序的第i个位置是哪个节点。
    for(auto y:son[x])
    {
        if(y!=pre)
        {
            dfs(y,x);
            S[x]+=S[y];
        }
    }
}
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    gg(n);gg(m);
    len=(int)(sqrt(n));
    repd(i,1,n)
    {
        gg(col[i]);
    }
    int u,v;
    repd(i,1,n-1)
    {
        gg(u);
        gg(v);
        son[v].pb(u);
        son[u].push_back(v);
    }
    dfs(1,-1);
    repd(i,1,m)
    {
        gg(a[i].l);
        int temp=S[a[i].l];// 以a[i].l 为根的子树大小。
        a[i].l=info[a[i].l]; // a[i].l 在dfs序中的位置。
        a[i].r=a[i].l+temp-1; // 询问区间 右端点 在dfs序中的位置。
        a[i].id=i;
        pos[i]=i/len;  // 莫队分块的部分。
    }
    sort(a+1,a+1+m,cmp);
    repd(i,1,m)
    {
        while(l>a[i].l)
        {
            l--;
            add(l);
        }
        while(r<a[i].r)
        {
            r++;
            add(r);
        }
        while(l<a[i].l)
        {
            del(l);
            l++;
        }
        while(r>a[i].r)
        {
            del(r);
            r--;
        }
        ans[a[i].id]=Ans;
    }
    repd(i,1,m)
    {
        printf("%lld\n",ans[i]);
    }
    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    }
    else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}



Guess you like

Origin www.cnblogs.com/qieqiemin/p/11364636.html