zoukankan      html  css  js  c++  java
  • hdu5709 Claris Loves Painting

    给一棵 n 点的树,每个节点上有一个颜色 (c_i) ,q 次询问一个点的子树中与这个点距离不
    超过 d 的点的颜色有多少种。
    (强制在线)

    考虑开两棵线段树

    第一棵中的每个点维护这个点的子树内深度在([l,r])之间有多少个点

    第二棵的每个点维护这个点的子树内每种颜色的最小深度

    我们从叶子节点向上合并,先合并第一棵再合并第二棵,如果合并第二棵时有两个颜色相等的节点,就保留深度小的并在第一棵线段树里减去这个点的贡献

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    const int N = 5e5;
    using namespace std;
    int T,n,m,c[N + 5],f[N + 5],dep[N + 5],rt1[N + 5],rt2[N + 5],node_cnt,val[N * 40 + 5],lc[N * 40 + 5],rc[N * 40 + 5];
    inline int read()
    {
    	int X(0),w(0);char ch(0);
    	while (!isdigit(ch))w|=ch=='-',ch=getchar();
    	while (isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    	return w?-X:X;
    }
    void insert(int &k,int las,int l,int r,int x,int v)
    {
        k = ++node_cnt;
        val[k] = val[las] + v;
        lc[k] = lc[las];
        rc[k] = rc[las];
        if (l == r)
            return;
        int mid = l + r >> 1;
        if (x <= mid)
            insert(lc[k],lc[las],l,mid,x,v);
        else
            insert(rc[k],rc[las],mid + 1,r,x,v);
    }
    int merge1(int x,int y)
    {
        if (!x || !y)
            return x + y;
        int z = ++node_cnt;
        val[z] = val[x] + val[y];
        lc[z] = merge1(lc[x],lc[y]);
        rc[z] = merge1(rc[x],rc[y]);
        return z;
    }
    int merge2(int x,int y,int l,int r,int k)
    {
        if (!x || !y)
            return x + y;
        int z = ++node_cnt;
        if (l == r)
        {
            val[z] = min(val[x],val[y]);
            if (val[x] < val[y])
                insert(rt1[k],rt1[k],1,n,val[y],-1);
            else
                insert(rt1[k],rt1[k],1,n,val[x],-1);
            return z;
        }
        int mid = l + r >> 1;
        lc[z] = merge2(lc[x],lc[y],l,mid,k);
        rc[z] = merge2(rc[x],rc[y],mid + 1,r,k);
        return z;
    }
    int query(int k,int l,int r,int x)
    {
        if (!k)
            return 0;
        if (r <= x)
            return val[k];
        int mid = l + r >> 1;
        if (x <= mid)
            return query(lc[k],l,mid,x);
        else
            return query(lc[k],l,mid,x) + query(rc[k],mid + 1,r,x);
    }
    int main()
    {
        T = read();
        while (T--)
        {
            n = read();
            m = read();
            for (int i = 1;i <= n;i++)
                c[i] = read();
            dep[1] = 1;
            for (int i = 2;i <= n;i++)
                f[i] = read(),dep[i] = dep[f[i]] + 1;
            for (int i = 1;i <= n;i++)
            {
                insert(rt1[i],0,1,n,dep[i],1);
                insert(rt2[i],0,1,n,c[i],dep[i]);
            }
            for (int i = n;i >= 2;i--)
            {
                rt1[f[i]] = merge1(rt1[i],rt1[f[i]]);
                rt2[f[i]] = merge2(rt2[i],rt2[f[i]],1,n,f[i]);
            }
            int ans = 0;
            int x,d;
            while (m--)
            {
                x = read();
                d = read();
                x ^= ans;
                d ^= ans;
                d = min(n,d + dep[x]);
                ans = query(rt1[x],1,n,d);
                printf("%d
    ",ans);
            }
            ans = node_cnt = 0;
        }
        return 0;
    }
    
  • 相关阅读:
    MySQL练习题
    InnoDB存储引擎+显示数据库引擎
    EMP+DEPT+SALGRADE 表的基本操作2
    EMP+DEPT+SALGRADE 表的基本操作1
    Git的使用
    JavaScript动画实例:旋转的正三角形
    JavaScript动画实例:曲线的绘制
    JavaScript动画实例:螺旋线
    JavaScript图形实例:阿基米德螺线
    JavaScript图形实例:平面镶嵌图案
  • 原文地址:https://www.cnblogs.com/sdlang/p/13428560.html
Copyright © 2011-2022 走看看