zoukankan      html  css  js  c++  java
  • CF208E

    跟上一题几乎是一模一样的套路。

    离线+倍增预处理+开以深度为权值的线段树。

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+10;
    int n,m,f[maxn][20];
    int root[maxn],tot;
    int dep[maxn];
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    	return x*f;
    }
    int beg[maxn],nex[maxn],to[maxn],e;
    inline void add(int x,int y){
    	e++;nex[e]=beg[x];
    	beg[x]=e;to[e]=y;
    }
    inline void dfs(int x,int fa){
    	dep[x]=dep[fa]+1;
    	for(int i=1;i<=15;i++)
    		f[x][i]=f[f[x][i-1]][i-1];
    	for(int i=beg[x];i;i=nex[i])
    		dfs(to[i],x);
    }
    vector<pair<int,int> >q[maxn];
    struct node{
    	int val,lc,rc;
    }tr[maxn*20];
    int rt[maxn],Max,cnt,ans[maxn];
    inline int update(int h,int l,int r,int x){
    	if(!h)h=++cnt;
    	tr[h].val++;
    	if(l==r)return h;
    	int mid=(l+r)>>1;
    	if(mid>=x)tr[h].lc=update(tr[h].lc,l,mid,x);
    	else tr[h].rc=update(tr[h].rc,mid+1,r,x);
    	return h;
    }
    inline int merge(int a,int b,int l,int r){
    	if(!a)return b;
    	if(!b)return a;
    	tr[a].val+=tr[b].val;
    	if(l==r)return a;
    	int mid=(l+r)>>1;
    	tr[a].lc=merge(tr[a].lc,tr[b].lc,l,mid);
    	tr[a].rc=merge(tr[a].rc,tr[b].rc,mid+1,r);
    	return a;
    }
    inline int query(int h,int l,int r,int x){
    	if(l==r)return tr[h].val;
    	int mid=(l+r)>>1;
    	if(mid>=x)return query(tr[h].lc,l,mid,x);
    	else return query(tr[h].rc,mid+1,r,x); 
    }
    inline void solve(int x,int fa){
    	rt[x]=update(rt[x],1,Max,dep[x]);
    	for(int i=beg[x];i;i=nex[i]){
    		int t=to[i];
    		solve(t,x);
    		rt[x]=merge(rt[x],rt[t],1,Max);
    	}
    	int a,b;
    	for(int i=0;i<q[x].size();i++){
    		a=q[x][i].first;b=q[x][i].second;
    		ans[b]=query(rt[x],1,Max,dep[x]+a)-1;
    	}
    }
    int main(){
    	n=read();
    	for(int i=1;i<=n;i++){
    		f[i][0]=read();
    		if(f[i][0])add(f[i][0],i);
    		else root[++tot]=i;
    	}
    	for(int i=1;i<=tot;i++)
    		dfs(root[i],0);
    	for(int i=1;i<=n;i++)
    		Max=max(Max,dep[i]);
    	m=read();
    	int x,y;
    	for(int i=1;i<=m;i++){
    		x=read(),y=read();
    		int tmp=dep[x]-y;
    		for(int j=15;j>=0;j--)
    			if(dep[f[x][j]]>=tmp)x=f[x][j];
    		q[x].push_back(make_pair(y,i));
    	}
    	for(int i=1;i<=tot;i++)
    		solve(root[i],0);
    	for(int i=1;i<=m;i++)
    		printf("%d ",ans[i]);	
    	return 0;
    }
    

    手打一遍过……

    深深地感到自己的弱小。

  • 相关阅读:
    [算法学习] 单调栈
    UVA11275 3D Triangles(三维几何)
    2019CCSU11月校赛 B,G题解
    2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17)(B,D)
    2016湖南省省赛 B 有向无环图(树形dp)
    2016湖南省省赛 J 三角形和矩形(计算几何)
    JAVA 高精度小数模板
    2019湖南省赛 K 双向链表练习题(list)
    2019 字节跳动 [编程题]最大映射(贪心)
    HDU 6740 MUV LUV EXTRA(kmp原理)
  • 原文地址:https://www.cnblogs.com/syzf2222/p/13155862.html
Copyright © 2011-2022 走看看