牛オフ練習試合60のE.一致相手ツリーヒューリスティック[合併]

ポータル

問題の解決策

このすべての統計サブツリーの問題は、ツリーのヒューリスティックとの合併を行うことは確かに可能です。
各点までの距離、ルートノードと重いの息子を前処理します。
ヒューリスティック合併をやって起動し、キーは各ノードにどのように統計的な答えです。
ここで私は答えの前に、各ノードの統計情報、パーティションのポイント処理の考え方を参照してください、私はサブツリーそのすべての情報を持っている、と私はそのサブツリー、サブツリー風雲の完全なトラバーサルを取得しようとしましたすべてのノードが取り出され、そしてあなたは、ツリーのサブポイントで計算を避けることができるように答えに関する統計は、それは、配列の統計カウント終了後に添加されます。実際には、従来の統計的手法は、ガバナンスを点在しました。
ポイントは、光の息子である場合、親に戻って来るとき、直接配列にそれを横断する、もちろん、ないのmemset、すべての情報をクリアすることができます数えます。この点は再息子である場合もカウントされなければならない、自分自身を忘れないでください。

コード

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <queue>
#define xx first
#define yy second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int inf=0x3f3f3f3f;
const LL INF=0x3f3f3f3f3f3f3f3f;
const int N=3e5+10;
const int M=1e6+10;
int n,k,a[N],dep[N],siz[N],son[N];
LL ans[N],temp[N],cnt,suma[N],depcnt[N];
int head[N],to[N*2],nxt[N*2],tot;
void add(int u,int v) {to[++tot]=v;nxt[tot]=head[u];head[u]=tot;}

void predfs(int u,int fa){
	siz[u]=1;dep[u]=dep[fa]+1;
	for(int i=head[u];i;i=nxt[i]){
		int v=to[i];
		if(v==fa) continue;
		predfs(v,u);
		siz[u]+=siz[v];
		if(siz[v]>siz[son[u]]) son[u]=v;
	}
}

void getnode(int u,int fa){
	temp[++cnt]=u;
	for(int i=head[u];i;i=nxt[i]) if(to[i]!=fa) getnode(to[i],u);
}

void clear(int u,int fa){
	suma[dep[u]]=depcnt[dep[u]]=0;
	for(int i=head[u];i;i=nxt[i]) if(to[i]!=fa) clear(to[i],u);
}

void dfs(int u,int fa,bool keep){
	for(int i=head[u];i;i=nxt[i]){
		int v=to[i];
		if(v==fa||v==son[u]) continue;
		dfs(v,u,false);
	}
	if(son[u]) dfs(son[u],u,true);
	for(int ii=head[u];ii;ii=nxt[ii]){
		int v=to[ii];
		if(v==fa||v==son[u]) continue;
		cnt=0;
		getnode(v,u);
		for(int i=1;i<=cnt;i++)
			if(dep[temp[i]]-dep[u]<k){
				int depv=k+2*dep[u]-dep[temp[i]];
				ans[u]+=suma[depv]+depcnt[depv]*a[temp[i]];
			}
		for(int i=1;i<=cnt;i++) suma[dep[temp[i]]]+=a[temp[i]],depcnt[dep[temp[i]]]++;
	}
	suma[dep[u]]+=a[u],depcnt[dep[u]]++;
	if(!keep) clear(u,fa);
}

int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1,u,v;i<n;i++){
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
	predfs(1,0);
	dfs(1,0,true);
	for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
	return 0;
} 

DD速度ベクトルについてTucao、前方に正直にそれで最高の連鎖スター。

おすすめ

転載: www.cnblogs.com/BakaCirno/p/12604767.html