[树 树状数组] SRM659 1100pts

题目大意:

题解:


#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(int &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=2005;
  
struct edge{  
    int u,v;  
    int next;  
};  
  
edge G[N<<1];  
int head[N],inum;  
  
inline void add(int u,int v,int p){  
    G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;  
}

int n,K,ans;

namespace BIT{
	int c[N<<1][N];
	void add(int x,int r){
		for(int i=x;i;i-=i&-i)
			++*c[i],c[i][*c[i]]=max(c[i][*c[i]-1],r);
	}
	void del(int x){
		for(int i=x;i;i-=i&-i) --*c[i];
	}
	int query(int x){
		int ret=0;
		for(int i=x;i<=2*(n+1);i+=i&-i) 
			ret=max(ret,c[i][*c[i]]);
		return ret;
	}
}

int f[N],e1[N],e2[N],g1[N],g2[N],g3[N],h1[N],h2[N];

#define V G[p].v

void dfs(int u,int fa)
{
	f[u]=g1[u]=g2[u]=g3[u]=0,e1[u]=e2[u]=h1[u]=h2[u]=0;
	for(int p=head[u];p;p=G[p].next)
		if(V!=fa)
		{
			dfs(V,u);
			f[u]=max(f[u],f[V]);
			if(f[V]>f[e1[u]])
				e2[u]=e1[u],e1[u]=V;
			else if(f[V]>f[e2[u]])
				e2[u]=V;
			if(g1[V]+1>g1[u])
			{
				g3[u]=g2[u],g2[u]=g1[u],g1[u]=g1[V]+1;
				h2[u]=h1[u],h1[u]=V;
			}
			else if(g1[V]+1>g2[u])
			{
				g3[u]=g2[u],g2[u]=g1[V]+1;
				h2[u]=V;
			}
			else if(g1[V]+1>g3[u])
			{
				g3[u]=g1[V]+1;
			}
		}
	f[u]=max(f[u],g1[u]+g2[u]);
}

#define DX n+1

void Dfs(int u,int fa,int deep,int Max)
{
	if(deep>Max) return;
	int now=BIT::query(K-g1[u]-deep+1+DX);
	now=K+deep-now-g1[u]+1;
	if(now>=deep && f[u]<=K) ans++;
	for(int p=head[u];p;p=G[p].next)
		if(V!=fa)
		{
			now=0;
			if(V==e1[u])
				now=max(now,f[e2[u]]);
			else 
				now=max(now,f[e1[u]]);
			if(V==h1[u])
				now=max(now,g2[u]+g3[u]);
			else if(V==h2[u])
				now=max(now,g1[u]+g3[u]);
			else 
				now=max(now,g1[u]+g2[u]);
			if(now>K) continue;
			int val;
			if(V==h1[u]) 
				val=g2[u];
			else 
				val=g1[u];
			now=BIT::query(K-val-deep+1+DX);
			if(!now) now=-1<<30;
			now=K+deep-now-val+1;
			BIT::add(val-deep+DX,val+deep);
			Dfs(V,u,deep+1,min(Max,now));
			BIT::del(val-deep+DX);
		}
}

int main()
{
	int iu;  
	freopen("build.in","r",stdin);  
	freopen("build.out","w",stdout);
	read(n); read(K);
	for (int i=2;i<=n;i++)
		read(iu),iu++,add(iu,i,++inum),add(i,iu,++inum);
	for(int i=1;i<=n;i++)
	{
		dfs(i,0);
		if(f[i]<=K)
		{
			ans+=n+1;
			continue;
		}
		Dfs(i,0,1,1<<30);
	}
	ans/=2;
	printf("%d\n",ans);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值