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;
    }
    
  • 相关阅读:
    Delphi XE5 android 蓝牙通讯传输
    Delphi XE5 android toast
    Delphi XE5 android openurl(转)
    Delphi XE5 如何设计并使用FireMonkeyStyle(转)
    Delphi XE5 android 捕获几个事件
    Delphi XE5 android listview
    Delphi XE5 android 黑屏的临时解决办法
    Delphi XE5 android popumenu
    Delphi XE5 android 获取网络状态
    Delphi XE5 android 获取电池电量
  • 原文地址:https://www.cnblogs.com/sdlang/p/13428560.html
Copyright © 2011-2022 走看看