1. 程式人生 > >Luogu P2982 [USACO10FEB]慢下來 Slowing down | dfs序、線段樹

Luogu P2982 [USACO10FEB]慢下來 Slowing down | dfs序、線段樹

urn inf end wid class int 題目 分享圖片 分享

題目鏈接

題目大意:

有一棵N個結點樹和N頭奶牛,一開始所有奶牛都在一號結點,奶牛們將按從編號1到編號N的順序依次前往自己的目的地,求每頭奶牛在去往自己目的地的途中將會經過多少已經有奶牛的結點。

題解:

可以發現,每一頭奶牛到達目的地後,都只會對還未到達目的地的奶牛中,目的地在它目的地子樹中的奶牛的答案產生貢獻。

比如說在下面這棵樹中,一頭奶牛到達了圖中深色結點,那麽在還未到達目的地的奶牛中,只有目的地在深色結點子樹中的奶牛才會由深色結點對答案產生貢獻。

技術分享圖片

所以,我們可以在每頭奶牛到達目的地後,將其目的地所在結點的子樹中每一個結點的權值都加上一,詢問時輸出該奶牛目的地所在結點的權值即可。

由於每一次的修改操作都是在一棵子樹內進行的,所以考慮用dfs序給結點編號(因為每棵子樹中結點的dfs序都一定是連續的一段),再用線段樹進行維護就好。

代碼:

#include<iostream>
#include<cstdio>
    using namespace std;
struct edge
{
    int last;
    int end;
}e[200005];
    int ne=0,idx=0,dfn[100005],note[100005],size[100005],tree[400005],lazy[400005];
void make_edge(int u,int
v) { ne++; e[ne].last=note[u]; e[ne].end=v; note[u]=ne; } void dfs(int x,int fx) { dfn[x]=++idx;//用dfs序給結點編號 size[x]=1; for(int i=note[x];i;i=e[i].last) if(e[i].end!=fx) { dfs(e[i].end,x);//繼續dfs //計算每個結點的子樹大小,用於計算此結點的子樹中最大的dfs序是多少,便於操作
size[x]+=size[e[i].end]; } } //線段樹板子 void add_node(int p,int l,int r,int k) { tree[p]+=(r-l+1)*k; lazy[p]+=k; } void clean_lazy(int p,int l,int r) { int mid=(l+r)>>1; add_node((p<<1),l,mid,lazy[p]); add_node((p<<1)+1,mid+1,r,lazy[p]); lazy[p]=0; } void add(int p,int l,int r,int x,int y) { if(x>y) return; if(l==x&&r==y) { add_node(p,l,r,1); return; } clean_lazy(p,l,r); int mid=(l+r)>>1; if(y<=mid) add((p<<1),l,mid,x,y); else if(x>mid) add((p<<1)+1,mid+1,r,x,y); else add((p<<1),l,mid,x,mid),add((p<<1)+1,mid+1,r,mid+1,y); } int ask(int p,int l,int r,int x) { if(l==r) return tree[p]; clean_lazy(p,l,r); int mid=(l+r)>>1; if(x<=mid) return ask((p<<1),l,mid,x); return ask((p<<1)+1,mid+1,r,x); } int main() { int n=0; scanf("%d",&n); for(int i=1;i<n;i++) { int u=0,v=0; scanf("%d%d",&u,&v); make_edge(u,v); make_edge(v,u); } dfs(1,0); for(int i=1;i<=n;i++) { int x=0; scanf("%d",&x); printf("%d\n",ask(1,1,n,dfn[x]));//直接輸出目的地所在的權值 add(1,1,n,dfn[x]+1,dfn[x]+size[x]-1);//給當前目的地所在結點的子樹中所有結點的權值都加1 } return 0; }

Luogu P2982 [USACO10FEB]慢下來 Slowing down | dfs序、線段樹