• bzoj 4771 七彩树


    bzoj

    hdu

    先考虑离线做法,可以按深度离线,然后按照深度顺序加点,那么询问就可以变成在(dep_x+d)深度时进行子树查询.现在考虑一个点,它可以给所有它的祖先答案+1,但是如果有一个同色的点,那么在他们的(lca)处以及(lca)祖先只会有(1)的贡献,所以加入一个点就单点+1,加入一个同色点要把它和(dfs)序前面一个以及后面一个点的(lca)-1(还要先消掉之前前去后继(lca)的-1).其实就是维护每种颜色的链并.然后可以发现子树权值和就是对应答案

    现在强制在线,可以先离线预处理,然后维护对应深度的可持久化线段树.每次查询找到对应最深深度的线段树直接查

    #include<bits/stdc++.h>
    #define LL long long
    #define uLL unsigned long long
    #define db double
    
    using namespace std;
    const int N=1e5+10;
    int rd()
    {
    	int x=0,w=1;char ch=0;
    	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    	return x*w;
    }
    int to[N<<1],nt[N<<1],hd[N],tot=1;
    void add(int x,int y)
    {
    	++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
    	++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
    }
    int n,m,q;
    int s[N*100],ch[N*100][2],rt[N],tt;
    void inst(int o1,int o2,int x,int y)
    {
    	s[o1]=s[o2]+y;
    	int l=1,r=n;
    	while(l<r)
    	{
    		int mid=(l+r)>>1;
    		if(x<=mid)
    		{
    			ch[o1][0]=++tt,ch[o1][1]=ch[o2][1];
    			o1=ch[o1][0],o2=ch[o2][0];
    			r=mid;
    		}
    		else
    		{
    			ch[o1][0]=ch[o2][0],ch[o1][1]=++tt;
    			o1=ch[o1][1],o2=ch[o2][1];
    			l=mid+1;
    		}
    		s[o1]=s[o2]+y;
    	}
    }
    int quer(int o,int l,int r,int ll,int rr)
    {
    	if(!o) return 0;
    	if(ll<=l&&r<=rr) return s[o];
    	int an=0,mid=(l+r)>>1;
    	if(ll<=mid) an+=quer(ch[o][0],l,mid,ll,rr);
    	if(rr>mid) an+=quer(ch[o][1],mid+1,r,ll,rr);
    	return an;
    }
    int co[N],fa[N],sz[N],de[N],hs[N],top[N],dfn[N],ti;
    void dfs1(int x)
    {
    	sz[x]=1;
    	for(int i=hd[x];i;i=nt[i])
    	{
    		int y=to[i];
    		if(y==fa[x]) continue;
    		fa[y]=x,de[y]=de[x]+1,dfs1(y);
    		sz[x]+=sz[y],hs[x]=sz[hs[x]]>sz[y]?hs[x]:y;
    	}
    }
    void dfs2(int x)
    {
    	dfn[x]=++ti;
    	if(hs[x]) top[hs[x]]=top[x],dfs2(hs[x]);
    	for(int i=hd[x];i;i=nt[i])
    	{
    		int y=to[i];
    		if(y==fa[x]||y==hs[x]) continue;
    		top[y]=y,dfs2(y);
    	}
    }
    int glca(int x,int y)
    {
    	while(top[x]!=top[y])
    	{
    		if(de[top[x]]<de[top[y]]) swap(x,y);
    		x=fa[top[x]];
    	}
    	return de[x]<de[y]?x:y;
    }
    struct node
    {
    	int x;
    	bool operator < (const node &bb) const {return dfn[x]<dfn[bb.x];}
    };
    set<node> sb[N];
    set<node>::iterator ft,nx;
    int sq[N];
    bool cmp(int aa,int bb){return de[aa]!=de[bb]?de[aa]<de[bb]:dfn[aa]<dfn[bb];}
    
    int main()
    {
    //f**k
    	int T=rd();
    	while(T--)
    	{
    		n=rd(),q=rd();
    		for(int i=1;i<=n;++i) fa[i]=hs[i]=top[i]=0;
    		for(int i=1;i<=n;++i) sb[i].clear(),co[i]=rd();
    		memset(hd,0,sizeof(int)*(n+1)),tot=1,ti=0;
    		for(int i=2;i<=n;++i) add(rd(),i);
    		de[1]=1,dfs1(1);
    		top[1]=1,dfs2(1);
    		m=0;
    		for(int i=1;i<=n;++i) m=max(m,de[i]);
    		for(int i=1;i<=n;++i) sq[i]=i;
    		sort(sq+1,sq+n+1,cmp);
    		while(tt)
    		{
    			s[tt]=ch[tt][0]=ch[tt][1]=0;
    			--tt;
    		}
    		for(int i=1,j=1;i<=m;++i)
    		{
    			rt[i]=rt[i-1];
    			while(j<=n&&de[sq[j]]==i)
    			{
    				int x=sq[j],las=rt[i];
    				inst(rt[i]=++tt,las,dfn[x],1);
    				if(!sb[co[x]].empty())
    				{
    					nx=sb[co[x]].upper_bound((node){x});
    					if(nx!=sb[co[x]].begin())
    					{
    						ft=--nx;
    						++nx;
    						las=rt[i],inst(rt[i]=++tt,las,dfn[glca(x,(*ft).x)],-1);
    						if(nx!=sb[co[x]].end()) las=rt[i],inst(rt[i]=++tt,las,dfn[glca((*ft).x,(*nx).x)],1);
    					}
    					if(nx!=sb[co[x]].end())
    					{
    						las=rt[i],inst(rt[i]=++tt,las,dfn[glca(x,(*nx).x)],-1);
    					}
    				}
    				sb[co[x]].insert((node){x});
    				++j;
    			}
    		}
    		int ans=0;
    		while(q--)
    		{
    			int x=rd()^ans,d=min((rd()^ans)+de[x],m);
    			printf("%d
    ",(ans=quer(rt[d],1,n,dfn[x],dfn[x]+sz[x]-1)));
    		}
    	}
    	return 0; 
    }
    
  • 相关阅读:
    Android碰到的怪问题
    Linux转换文件格式
    Android 打包签名 从生成keystore到完成签名
    重写SimpleCursorAdapter
    sqlite的数据导入 导出
    日语单词检索WebService 账户API和示例更新
    日语单词检索 WebService 试运行 和简单说明
    使用扩展方法,让菜单也可以Clone
    接口里面的静态方法痒啊
    创业难,守业更难
  • 原文地址:https://www.cnblogs.com/smyjr/p/11530852.html
Copyright © 2020-2023  润新知