• BZOJ4771: 七彩树


    题解: 对于每个节点 他只会对这个节点到根这条路径上的点产生贡献 所以我们考虑树链的并 找到每个节点能作用的深度最低的位置  然后对于深度建主席树,权值为dfs序的下标 通过set来维护树链的并 最后查询即可

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=1e5+10;
    const double eps=1e-8;
    #define ll long long
    using namespace std;
    struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    typedef struct node{
        int l,r,sum;
    }node;
    node d[MAXN*81];
    int f[MAXN][21],dep[MAXN],p[MAXN],fp[MAXN],cnt,cnt1,rt[MAXN],a[MAXN],n,q,num[MAXN],id[MAXN];
    set<int>s[MAXN];
    set<int>::iterator ite,ip;
    void dfs(int x,int fa,int deep){
        f[x][0]=fa;dep[x]=deep+1;p[x]=++cnt;fp[p[x]]=x;num[x]=1;
        link(x){
            if(j->t!=fa)dfs(j->t,x,deep+1),num[x]+=num[j->t];
        }
    }
    void dfs1(int x){
        for(int i=1;i<=20;i++)f[x][i]=f[f[x][i-1]][i-1];
        link(x)if(j->t!=f[x][0])dfs1(j->t);
    }
    int Lca(int u,int v){
        if(dep[u]<dep[v])swap(u,v);
        int tmp=dep[u]-dep[v];
        inc(i,0,20)if(tmp&(1<<i))u=f[u][i];
        if(u==v)return u;
        dec(i,20,0){
            if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
        }
        return f[u][0];
    }
    void update(int &x,int y,int l,int r,int t,int vul){
        x=++cnt1;d[x]=d[y];d[x].sum+=vul;
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(t<=mid)update(d[x].l,d[y].l,l,mid,t,vul);
        else update(d[x].r,d[y].r,mid+1,r,t,vul);
    }
    int ans;
    void querty(int x,int y,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){ans+=d[y].sum-d[x].sum;return ;}
        int mid=(l+r)>>1;
        if(ql<=mid)querty(d[x].l,d[y].l,l,mid,ql,qr);
        if(qr>mid)querty(d[x].r,d[y].r,mid+1,r,ql,qr);
    }
    bool cmp(int aa,int bb){return dep[aa]<dep[bb];}
    int main(){
        int _=read();
        while(_--){
            cnt=cnt1=0;n=read();q=read();memset(e,0,sizeof(e));memset(h,0,sizeof(h));o=e;
            inc(i,1,n)id[i]=i,a[i]=read(),s[i].clear();
            int u,v;
            inc(i,2,n)u=read(),add(i,u),add(u,i);
            dfs(1,0,0);dfs1(1);
            sort(id+1,id+n+1,cmp);
            int tot=1;
            inc(i,1,n){
                rt[i]=++cnt1;d[rt[i]]=d[rt[i-1]];
                while(tot<=n&&dep[id[tot]]<=i){
                    update(rt[i],rt[i],1,n,p[id[tot]],1);
                    ite=s[a[id[tot]]].lower_bound(p[id[tot]]);
                    int x=0,y=0;
                    if(ite!=s[a[id[tot]]].begin())ip=ite,ip--,x=fp[(*ip)],update(rt[i],rt[i],1,n,p[Lca(id[tot],x)],-1);
                    if(ite!=s[a[id[tot]]].end())ip=ite,y=fp[(*ip)],update(rt[i],rt[i],1,n,p[Lca(id[tot],y)],-1);
                    if(x&&y)update(rt[i],rt[i],1,n,p[Lca(x,y)],1);
                    s[a[id[tot]]].insert(p[id[tot]]);tot++;
                }
            }
            int res=0,x,d;
            while(q--){
                x=read()^res;d=read()^res;
                ans=0;querty(rt[dep[x]-1],rt[min(dep[x]+d,n)],1,n,p[x],p[x]+num[x]-1);res=ans;
                printf("%d
    ",res);
            }
        }
    }
    

    4771: 七彩树

    Time Limit: 5 Sec  Memory Limit: 256 MB
    Submit: 1520  Solved: 432
    [Submit][Status][Discuss]

    Description

    给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点。每个节点都被染上了某一种颜色,其中第i个节
    点的颜色为c[i]。如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色。定义depth[i]为i节点与根节点的距离
    ,为了方便起见,你可以认为树上相邻的两个点之间的距离为1。站在这棵色彩斑斓的树前面,你将面临m个问题。
    每个问题包含两个整数x和d,表示询问x子树里且depth不超过depth[x]+d的所有点中出现了多少种本质不同的颜色
    。请写一个程序,快速回答这些询问。

    Input

    第一行包含一个正整数T(1<=T<=500),表示测试数据的组数。
    每组数据中,第一行包含两个正整数n(1<=n<=100000)和m(1<=m<=100000),表示节点数和询问数。
    第二行包含n个正整数,其中第i个数为c[i](1<=c[i]<=n),分别表示每个节点的颜色。
    第三行包含n-1个正整数,其中第i个数为f[i+1](1<=f[i]<i),表示节点i+1的父亲节点的编号。
    接下来m行,每行两个整数x(1<=x<=n)和d(0<=d<n),依次表示每个询问。
    输入数据经过了加密,对于每个询问,如果你读入了x和d,那么真实的x和d分别是x xor last和d xor last,
    其中last表示这组数据中上一次询问的答案,如果这是当前数据的第一组询问,那么last=0。
    输入数据保证n和m的总和不超过500000。

    Output

    对于每个询问输出一行一个整数,即答案。

    Sample Input

    1
    5 8
    1 3 3 2 2
    1 1 3 3
    1 0
    0 0
    3 0
    1 3
    2 1
    2 0
    6 2
    4 1

    Sample Output

    1
    2
    3
    1
    1
    2
    1
    1

     

  • 相关阅读:
    MVC动态添加文本框,后台使用FormCollection接收
    使用结构struct作为Dictionary<TKey,TValue>的键
    扩展方法的几个实例,扩展基本类型、接口、通过反射让扩展方法使用私有成员等
    使用Enum.TryParse()实现枚举的安全转换
    .NET泛型04,使用Lazy<T>实现延迟加载
    .NET泛型03,泛型类型的转换,协变和逆变
    .NET泛型02,泛型的使用
    dd、split、csplit命令
    seq命令
    uniq命令
  • 原文地址:https://www.cnblogs.com/wang9897/p/9753641.html
Copyright © 2020-2023  润新知