洛谷P3258 [JLOI2014]松鼠的新家
阿新 • • 發佈:2018-12-31
== using () isdigit 題目 val return 裝修 路線 是餐廳,餐廳裏他準備了豐盛的大餐,所以當維尼在參觀的最後到達餐廳時就不需要再拿糖果吃了。
題目描述
松鼠的新家是一棵樹,前幾天剛剛裝修了新家,新家有n個房間,並且有\(n-1\)根樹枝連接,每個房間都可以相互到達,且倆個房間之間的路線都是唯一的。天哪,他居然真的住在”樹“上。
松鼠想邀請小熊維尼前來參觀,並且還指定一份參觀指南,他希望維尼能夠按照他的指南順序,先去\(a_1\),再去\(a_2\),......,最後到\(a_n\),去參觀新家。可是這樣會導致維尼重復走很多房間,懶惰的維尼不停地推辭。可是松鼠告訴他,每走到一個房間,他就可以從房間拿一塊糖果吃。
維尼是個饞家夥,立馬就答應了。現在松鼠希望知道為了保證維尼有糖果吃,他需要在每一個房間各放至少多少個糖果。
因為松鼠參觀指南上的最後一個房間\(a_n\)
輸入輸出格式
輸入格式:
第一行一個整數\(n\),表示房間個數第二行\(n\)個整數,依次描述\(a_1-a_n\)
接下來\(n-1\)行,每行兩個整數\(x\),\(y\),表示標號\(x\)和\(y\)的兩個房間之間有樹枝相連。
輸出格式:
一共\(n\)行,第\(i\)行輸出標號為\(i\)的房間至少需要放多少個糖果,才能讓維尼有糖果吃。
輸入輸出樣例
輸入樣例#1:
5
1 4 5 3 2
1 2
2 4
2 3
4 5
輸出樣例#1:
1
2
1
2
1
說明
\(2 \leq n \leq 300000\)
思路:考慮樹鏈剖分+線段樹,我們自己手玩樣例可以發現,我們按題目中給出的結點訪問順序進行路徑修改,最後把每條路徑的起點的點權\(-1\)(除了起始結點),就是答案了,然後就是一個樹鏈剖分的裸題了。
代碼:
#include<cstdio> #include<algorithm> #include<cctype> #define maxn 300007 #define ls rt<<1 #define rs rt<<1|1 using namespace std; int n,m,head[maxn],d[maxn],son[maxn],siz[maxn],id[maxn],w[maxn]; int num,cnt,sum[maxn<<2],top[maxn],fa[maxn],lazy[maxn<<2]; inline int qread() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num*f; } struct node { int v,nxt; }e[maxn<<1]; inline void ct(int u, int v) { e[++num].v=v; e[num].nxt=head[u]; head[u]=num; } inline void pushdown(int rt) { if(lazy[rt]) { sum[ls]+=lazy[rt],sum[rs]+=lazy[rt]; lazy[ls]+=lazy[rt],lazy[rs]+=lazy[rt]; lazy[rt]=0; } } void modify(int rt, int l, int r, int L, int R, int val) { if(L>r||R<l) return; if(L<=l&&r<=R) { sum[rt]+=val; lazy[rt]+=val; return; } pushdown(rt); int mid=(l+r)>>1; modify(ls,l,mid,L,R,val),modify(rs,mid+1,r,L,R,val); } int query(int rt, int l, int r, int L) { if(l==r) return sum[rt]; int mid=(l+r)>>1; pushdown(rt); if(L<=mid) return query(ls,l,mid,L); else return query(rs,mid+1,r,L); } void dfs1(int u) { siz[u]=1; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(v!=fa[u]) { d[v]=d[u]+1; fa[v]=u; dfs1(v); siz[u]+=siz[v]; if(siz[v]>siz[son[u]]) son[u]=v; } } } void dfs2(int u, int t) { id[u]=++cnt; top[u]=t; if(son[u]) dfs2(son[u],t); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } } void cal(int x, int y) { int fx=top[x],fy=top[y]; while(fx!=fy) { if(d[fx]<d[fy]) swap(x,y),swap(fx,fy); modify(1,1,cnt,id[fx],id[x],1); x=fa[fx],fx=top[x]; } if(id[x]>id[y]) swap(x,y); modify(1,1,cnt,id[x],id[y],1); } int main() { n=qread(); for(int i=1;i<=n;++i) w[i]=qread(); for(int i=1,u,v;i<n;++i) { u=qread(),v=qread(); ct(u,v);ct(v,u); } dfs1(1),dfs2(1,1); int now=w[1]; for(int i=2;i<=n;++i) { cal(now,w[i]); now=w[i]; modify(1,1,cnt,id[now],id[now],-1); } for(int i=1;i<=n;++i) printf("%d\n",query(1,1,cnt,id[i])); return 0; }
洛谷P3258 [JLOI2014]松鼠的新家