JLOI2014 松鼠的新家

Time Limit: 10 Sec Memory Limit: 128 MB

Description

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有(n)个房间,并且有(n-1)根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请****前来参观,并且还指定一份参观指南,他希望**能够按照他的指南顺序,先去(a_1),再去(a_2),……,最后到(a_n),去参观新家。

可是这样会导致**重复走很多房间,懒惰的**不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。**是个馋家伙,立马就答应了。

现在松鼠希望知道为了保证**有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间(a_n)是餐厅,餐厅里他准备了丰盛的大餐,所以当**在参观的最后到达餐厅时就不需要再拿糖果吃了。

Input

第一行一个整数(n),表示房间个数

第二行(n)个整数,依次描述(a_1)-(a_n)

接下来(n-1)行,每行两个整数(x)(y),表示标号(x)(y)的两个房间之间有树枝相连。

Output

一共(n)行,第(i)行输出标号为i的房间至少需要放多少个糖果,才能让**有糖果吃。

Sample Input

5
1 4 5 3 2
1 2
2 4
2 3
4 5

Sample Output

1
2
1
2
1

HINT

(2leq n leq 300000)

Solution

没意思的题目,树上差分板子题,不过注意减掉每次末节点的重复即可。因为写的倍增LCA,可能比较慢。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
#define lowbit(x) ((x)&(-(x)))
#define REP(i,a,n) for(register int i=(a);i<=(n);++i)
#define PER(i,a,n) for(register int i=(a);i>=(n);--i)
#define FEC(i,x) for(register int i=head[x];i;i=g[i].ne)
#define dbg(...) fprintf(stderr,__VA_ARGS__)
#define lc o<<1
#define rc o<<1|1
namespace io{
	const int SIZE=(1<<21)+1;char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55];int f,qr;
	#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
	template<class I>inline void read(I &x){for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;}
	template<class I>inline void write(I x){if(!x)putc('0');if(x<0)putc('-'),x=-x;while(x)qu[++qr]=x%10+'0',x/=10;while(qr)putc(qu[qr--]);}
	struct Flusher_{~Flusher_(){flush();}}io_flusher_;
}//orz laofudasuan
using io::read;using io::putc;using io::write;
typedef long long ll;typedef unsigned long long ull;
template<typename A,typename B>inline bool SMAX(A&x,const B&y){return x<y?x=y,1:0;}
template<typename A,typename B>inline bool SMIN(A&x,const B&y){return y<x?x=y,1:0;}

const int N=300000+7,LOG=20;
int n,a[N],x,y,f[N][LOG],dep[N],tag[N],q[N],top;
struct Edge{int to,ne;}g[N<<1];int head[N],tot;
inline void Addedge(int x,int y){g[++tot].to=y;g[tot].ne=head[x];head[x]=tot;}

inline void DFS(int x,int fa=0){
	dep[x]=dep[fa]+1;f[x][0]=fa;for(register int i=1;i<LOG;++i)f[x][i]=f[f[x][i-1]][i-1];
	for(register int i=head[x];i;i=g[i].ne)if(g[i].to!=fa)DFS(g[i].to,x);q[++top]=x;
}
inline int LCA(int x,int y){
	if(dep[x]<dep[y])x^=y^=x^=y;
	for(register int i=LOG-1;i>=0;--i)if(dep[f[x][i]]>=dep[y])x=f[x][i];
	if(x==y)return x;
	for(register int i=LOG-1;i>=0;--i)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
	return f[x][0];
}

int main(){
#ifndef ONLINE_JUDGE
	freopen("BZOJ3631.in","r",stdin);freopen("BZOJ3631.out","w",stdout);
#endif
	read(n);for(register int i=1;i<=n;++i)read(a[i]);
	for(register int i=1;i<n;++i)read(x),read(y),Addedge(x,y),Addedge(y,x);
	DFS(1);
	for(register int i=2;i<=n;++i){
		int x=a[i-1],y=a[i],p=LCA(x,y);
		++tag[x],++tag[f[y][0]];--tag[p],--tag[f[p][0]];
	}
	for(register int i=1;i<=n;++i)tag[f[q[i]][0]]+=tag[q[i]];
	for(register int i=1;i<=n;++i)write(tag[i]),putc('
');
}
原文地址:https://www.cnblogs.com/hankeke/p/BZOJ3631.html