1. 程式人生 > >[JLOI2014]松鼠的新家(線段樹,樹鏈剖分)

[JLOI2014]松鼠的新家(線段樹,樹鏈剖分)

題目描述

松鼠的新家是一棵樹,前幾天剛剛裝修了新家,新家有n個房間,並且有n-1根樹枝連線,每個房間都可以相互到達,且倆個房間之間的路線都是唯一的。天哪,他居然真的住在”樹“上。

松鼠想邀請小熊維尼前來參觀,並且還指定一份參觀指南,他希望維尼能夠按照他的指南順序,先去a1,再去a2,......,最後到an,去參觀新家。可是這樣會導致維尼重複走很多房間,懶惰的維尼不停地推辭。可是松鼠告訴他,每走到一個房間,他就可以從房間拿一塊糖果吃。

維尼是個饞傢伙,立馬就答應了。現在松鼠希望知道為了保證維尼有糖果吃,他需要在每一個房間各放至少多少個糖果。

因為松鼠參觀指南上的最後一個房間an是餐廳,餐廳裡他準備了豐盛的大餐,所以當維尼在參觀的最後到達餐廳時就不需要再拿糖果吃了。

輸入輸出格式

輸入格式:

 

第一行一個整數n,表示房間個數第二行n個整數,依次描述a1-an

接下來n-1行,每行兩個整數x,y,表示標號x和y的兩個房間之間有樹枝相連。

 

輸出格式:

 

一共n行,第i行輸出標號為i的房間至少需要放多少個糖果,才能讓維尼有糖果吃。

思路:

又是一道樹剖板子題

對於小熊的訪問,我們可以看成是從在a[i]~a[i+1]的路徑上都增加了1

然後由於有重複,將每次將a[i+1]減1就好

程式碼:

#include<iostream>
#include<cstdio>
#include
<cstring> #include<bitset> #include<queue> #include<algorithm> //#define int long long #define rii register int i #define rij register int j using namespace std; int n; struct ljb{ int to,nxt; }x[900005]; struct node{ int val,lazy; }y[1200005]; int f[300005],sd[300005],head[300005
],val[300005],size[300005]; int weison[300005],cnt,bnt,nid[300005],nval[300005],ntop[300005]; int sx[1000005]; int res; void add(int from,int to) { cnt++; x[cnt].to=to; x[cnt].nxt=head[from]; head[from]=cnt; } void dfs1(int wz,int fa,int s) { sd[wz]=s; f[wz]=fa; size[wz]=1; int maxn=0; for(rii=head[wz];i!=0;i=x[i].nxt) { int to=x[i].to; if(to==fa) { continue; } dfs1(to,wz,s+1); size[wz]+=size[to]; if(size[to]>maxn) { maxn=size[to]; weison[wz]=to; } } } void dfs2(int wz,int top) { bnt++; nid[wz]=bnt; nval[bnt]=val[wz]; ntop[wz]=top; if(weison[wz]==0) { return; } dfs2(weison[wz],top); for(rii=head[wz];i!=0;i=x[i].nxt) { int to=x[i].to; if(weison[wz]==to||f[wz]==to) { continue; } dfs2(to,to); } } void build(int bh,int l,int r) { if(l==r) { y[bh].val=nval[l]; return; } int mid=(l+r)/2; build(bh*2,l,mid); build(bh*2+1,mid+1,r); y[bh].val+=y[bh*2].val+y[bh*2+1].val; } void pushdown(int bh,int cd) { y[bh*2].lazy+=y[bh].lazy; y[bh*2+1].lazy+=y[bh].lazy; y[bh*2].val+=y[bh].lazy*(cd-(cd/2)); y[bh*2+1].val+=y[bh].lazy*(cd/2); y[bh].lazy=0; } void updata(int bh,int nl,int nr,int l,int r,int val) { int len=(nr-nl+1); if(l<=nl&&nr<=r) { y[bh].lazy+=val; y[bh].val+=val*len; return; } if(y[bh].lazy!=0) { pushdown(bh,len); } int mid=(nl+nr)/2; if(l<=mid) { updata(bh*2,nl,mid,l,r,val); } if(r>mid) { updata(bh*2+1,mid+1,nr,l,r,val); } y[bh].val=(y[bh*2].val+y[bh*2+1].val); } void query(int bh,int nl,int nr,int l,int r) { if(l<=nl&&r>=nr) { res+=y[bh].val; return; } int mid=(nl+nr)/2; if(y[bh].lazy!=0) { pushdown(bh,nr-nl+1); } if(l<=mid) { query(bh*2,nl,mid,l,r); } if(r>mid) { query(bh*2+1,mid+1,nr,l,r); } } int querylj(int from,int to) { int ans=0; while(ntop[from]!=ntop[to]) { if(sd[ntop[from]]<sd[ntop[to]]) { swap(from,to); } res=0; query(1,1,n,nid[ntop[from]],nid[from]); ans+=res; from=f[ntop[from]]; } if(sd[from]>sd[to]) { swap(from,to); } res=0; query(1,1,n,nid[from],nid[to]); ans+=res; return ans; } void addlj(int from,int to,int val) { while(ntop[from]!=ntop[to]) { if(sd[ntop[from]]<sd[ntop[to]]) { swap(from,to); } updata(1,1,n,nid[ntop[from]],nid[from],val); from=f[ntop[from]]; } if(sd[from]>sd[to]) { swap(from,to); } updata(1,1,n,nid[from],nid[to],val); } signed main() { scanf("%d",&n); for(rii=1;i<=n;i++) { scanf("%d",&sx[i]); } for(rii=1;i<n;i++) { int fe,to; scanf("%d%d",&fe,&to); add(fe,to); add(to,fe); } dfs1(1,0,2); dfs2(1,1); build(1,1,n); for(rii=1;i<n;i++) { addlj(sx[i],sx[i+1],1); addlj(sx[i+1],sx[i+1],-1); } for(rii=1;i<=n;i++) { printf("%d\n",querylj(i,i)); } }