P1600 [NOIP2016 提高组] 天天爱跑步

这题被我 3 min 胡出来了的样子。

考虑,m 对点 $(s_i,t_i)$ 去贡献点 j。

考虑贡献式: $dep_s+dep_x-2dep_{lca(s,x)}=w_x$。

如果 $xin [s,lca(s,t)]$,那么 $dep_s-dep_x=w_x,dep_s=dep_x+w_x$,用 $dep_s_$ 去贡献即可。具体我不太会,用了个比较蠢的分块维护桶。

$ xin[lca(s,t),t]$,那么 $dep_s+dep_x-2*dep_{lca(s,x)}=w_x$,此时 $lca(s,x)=lca(s,t)$,$dep_s-2*dep{lca(s,t)}=w_x-dep_x$,考虑用这东西去贡献下就好。由于 $w_x-dep_x in[-n,n]$,要值域平移。

注意下空间。时复 $O(nsqrt{n}log n)$。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <map>

#define ll long long

using namespace std;
int rd() {
	int f=1,sum=0; char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return sum*f;
}
ll lrd() {
	ll f=1,sum=0; char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return sum*f;
}
/* dis=w_x dep_A+dep_x-2*dep_lca=w_x dep_A-2*dep_lca=w_x-dep_x
  分块,块内维护个桶
*/ 
const int N=(int)(3e5+2),M=410;
struct edge {
	int nex,to;
}e[N<<1];
int dep[N],fa[N],top[N],son[N],sz[N],id[N],rk[N],tot;
int head[N],cnt,w[N],ans[N],n,m;

void add_edge(int x,int y) {
	e[++cnt].nex=head[x]; e[cnt].to=y; head[x]=cnt;
}

void dfs1(int x,int ff) {
	dep[x]=dep[ff]+1; fa[x]=ff; sz[x]=1;
	for(int i=head[x];i;i=e[i].nex) {
		int y=e[i].to; if(y==ff) continue;
		dfs1(y,x); sz[x]+=sz[y];
		if(sz[y]>sz[son[x]]) son[x]=y;
	}
}

void dfs2(int x,int tp) {
	top[x]=tp; id[x]=++tot; rk[tot]=x; 
	if(son[x]) dfs2(son[x],tp);
	for(int i=head[x];i;i=e[i].nex) {
		int y=e[i].to; if(y==fa[x]||y==son[x]) continue;
		dfs2(y,y);
	}
}
#define K (int)(3e5)
int L[M],R[M],bid[N],bl,cnt1[M][N<<1],cnt2[M][N<<1];
void init() {
	bl=sqrt(1.0*n*1.8); 
	for(int i=1;i<=n;i++) bid[i]=(i-1)/bl+1;
	for(int i=1;i<=bid[n];i++) L[i]=(i-1)*bl+1,R[i]=i*bl; R[bid[n]]=n;	
}	

void upt1(int l,int r,int pos) {
	if(bid[l]==bid[r]) {
		for(int i=l;i<=r;i++) if(w[rk[i]]+dep[rk[i]]==pos) ++ans[i];
	} else {
		for(int i=l;i<=R[bid[l]];i++) if(w[rk[i]]+dep[rk[i]]==pos) ++ans[i];
		for(int i=L[bid[r]];i<=r;i++) if(w[rk[i]]+dep[rk[i]]==pos) ++ans[i];
		for(int i=bid[l]+1;i<bid[r];i++) ++cnt1[i][pos+K];
	}
}

void upt2(int l,int r,int pos) {
	if(bid[l]==bid[r]) {
		for(int i=l;i<=r;i++) if(w[rk[i]]-dep[rk[i]]==pos) ++ans[i];
	} else {
		for(int i=l;i<=R[bid[l]];i++) if(w[rk[i]]-dep[rk[i]]==pos) ++ans[i];
		for(int i=L[bid[r]];i<=r;i++) if(w[rk[i]]-dep[rk[i]]==pos) ++ans[i];
		for(int i=bid[l]+1;i<bid[r];i++) ++cnt2[i][pos+K];
	}
}

int query(int x) {
	//cout<<w[x]-dep[x]<<endl;
	return ans[x]+cnt1[bid[x]][w[rk[x]]+dep[rk[x]]+K]+cnt2[bid[x]][w[rk[x]]-dep[rk[x]]+K];
}

int LCA(int x,int y) {
	while(top[x]!=top[y]) {
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		x=fa[top[x]];
	}
	return dep[x]<dep[y]?x:y;
}

// dep_A-dep_x+dis=w_x w_x+dep_x=dep_A+dis
// dep_A-dep_x=w_x w_x+dep_x=dep_A
// all_dis-(dep_A-dep_x)=all_dis-dep_A+dep_x=w_x 
// w_x-dep_x=all_dis-dep_A
/*
dep_x+dep_y-2*dep_lca=w_y
dep_A-dep_x=w_x 
1. dep_x=w_y+dep_y
2. dep_x-2*dep_d=w_y-dep_y
*/
void update1(int x,int y) {
	int A=x;
	while(top[x]!=top[y]) {
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		upt1(id[top[x]],id[x],dep[A]);
		x=fa[top[x]];
	}
	if(id[x]>id[y]) swap(x,y);
	upt1(id[x],id[y],dep[A]);
}

void update2(int depd,int u,int x,int y) {
	int A=u;
	while(top[x]!=top[y]) {
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		upt2(id[top[x]],id[x],dep[A]-2*depd);
		x=fa[top[x]];
	}
	if(id[x]>id[y]) swap(x,y);
	upt2(id[x],id[y],dep[A]-2*depd);
}

void pr(int x) {
	if(x<0) {putchar('-');x=-x;}
	if(x>9) pr(x/10);
	putchar(x%10+'0');
}

int main() {
	int x,y;
	n=rd(); m=rd();
	for(int i=1;i<n;i++) {
		x=rd(); y=rd();
		add_edge(x,y); add_edge(y,x);
	}
	for(int i=1;i<=n;i++) w[i]=rd();
	dfs1(1,0); dfs2(1,0);
	init();
	while(m--) {
		x=rd(); y=rd(); int d=LCA(x,y);
		update1(x,d); update2(dep[d],x,y,d);
		if(dep[x]-dep[d]==w[d]) --ans[id[d]];
//		cout<<dep[x]+dep[y]-2*dep[d]<<":
";
	//	 puts("");
	}
	for(int i=1;i<=n;i++) pr(query(id[i])),putchar(' ');
	return 0;
}

  

原文地址:https://www.cnblogs.com/xugangfan/p/15222742.html