天天看點

NOIP 2016 天天愛跑步

NOIP 2016 天天愛跑步

洛谷傳送門

JDOJ傳送門

Description

Input

Output

Sample Input

6 3 2 3 1 2 1 4 4 5 4 6 0 2 5 1 2 3 1 5 1 3 2 6

Sample Output

2 0 0 1 1 1

HINT

題解:

先口胡一下部分分。

首先1号、2号,隻有0時刻出現的觀察員能夠看到人,所有人都在0時刻出現。那麼樹上差分統計人數即可。

3号、4号,也是隻有0時刻觀察員,隻統計起點即可。

5号,暴力可過。

9-12号,由于起點固定,是以每個人跑到每個點的時間可以用性質算出來,然後按這個性質統計即可。

13-16号同理。

那麼再考慮正解。

9-12和13-16号點可以給我們很大的啟發:我們發現針對起點為1、終點為1的路徑,都是按性質走的,是以我們就可以得到一個啟發:将一條路徑拆分成兩個支路來解決。這樣的話,這樣的兩條之路可以分别利用性質來處理。

這個性質是:在上行路徑上,滿足

\[deep[s]-deep[x]=t[x]

\]

這樣的點是對答案有貢獻的。

在下行路徑上,滿足

\[deep[s]+deep[x]-2\times deep[lca]=t[x]

那麼對于每一個節點\(x\),根據以上性質,就有\(deep[s]=deep[x]+t[x]\),也就是說,對于一條起點為s的上行路徑來講,它會對這個路徑上所有滿足這個性質的點作貢獻。

下行路徑同理。

那麼怎麼處理呢?思路到這裡,權值線段樹的想法就比較自然了。按起始節點s的深度deep[s]來統計人數。是以我們可以考慮用權值線段樹(動态開點)來維護這個資訊。然後通過樹上差分快速處理新路徑。最後隻需要從下到上線段樹合并統計即可。

注意,上行和下行要統計兩遍。

代碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
    int x=0,f=1;
    char ch=nc();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=nc();
    }
    while(ch>='0'&&ch<='9')
        x=x*10+ch-'0',ch=nc();
   	return x*f;
}
const int maxn=3*1e5+10;
int n,m,maxx;
int tot,to[maxn<<1],nxt[maxn<<1],head[maxn];
int t[maxn];
int top[maxn],fa[maxn],deep[maxn],size[maxn],son[maxn];
int b[maxn],e[maxn],lcaa[maxn];
int sum[maxn*50],lson[maxn*50],rson[maxn*50],cnt;
int root[maxn],ans[maxn];
void add(int x,int y)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}    
void dfs1(int x,int f)
{
    deep[x]=deep[f]+1;
    fa[x]=f;
    size[x]=1;
    for(int i=head[x];i;i=nxt[i])
    {
        int y=to[i];
        if(y==f)
            continue;
        dfs1(y,x);
        size[x]+=size[y];
        if(!son[x]||size[y]>size[son[x]])
            son[x]=y;
    }
}
void dfs2(int x,int t)
{
    top[x]=t;
    if(!son[x])
        return;
    dfs2(son[x],t);
    for(int i=head[x];i;i=nxt[i])
    {
        int y=to[i];
        if(y==fa[x]||y==son[x])
            continue;
        dfs2(y,y);
    }
}
int lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]])
            swap(x,y);
        x=fa[top[x]];
    }
    return deep[x]<deep[y]?x:y;
}
void pushup(int pos)
{
    sum[pos]=sum[lson[pos]]+sum[rson[pos]];
}
void update(int &pos,int l,int r,int x,int k)
{
    int mid=(l+r)>>1;
    if(!pos)
        pos=++cnt;
    if(l==r)
    {
        sum[pos]+=k;
        return;
    }
    if(x<=mid)
        update(lson[pos],l,mid,x,k);
    else
        update(rson[pos],mid+1,r,x,k);
    pushup(pos);
}
int query(int pos,int l,int r,int x)
{
    int mid=(l+r)>>1;
    if(l==r)
        return sum[pos];
    if(x<=mid)
        return query(lson[pos],l,mid,x);
    else
        return query(rson[pos],mid+1,r,x);
}
void merge(int &x,int y,int l,int r)
{
    int mid=(l+r)>>1;
    if(!x||!y)
    {
        x=(!x?y:x);
        return;
    }
    if(l==r)
        sum[x]+=sum[y];
    merge(lson[x],lson[y],l,mid);
    merge(rson[x],rson[y],mid+1,r);
}
void dfs3(int x)
{
    for(int i=head[x];i;i=nxt[i])
    {
        int y=to[i];
        if(y==fa[x])
            continue;
        dfs3(y);
        merge(root[x],root[y],1,maxx);
    }
    if(n+deep[x]+t[x]<=maxx)
        ans[x]+=query(root[x],1,maxx,n+deep[x]+t[x]);
}
void dfs4(int x)
{
    for(int i=head[x];i;i=nxt[i])
    {
        int y=to[i];
        if(y==fa[x])
            continue;
        dfs4(y);
        merge(root[x],root[y],1,maxx);
    }
    ans[x]+=query(root[x],1,maxx,n+deep[x]-t[x]);
}
int main()
{
    n=read();m=read();
    for(int i=1;i<n;i++)
    {
        int x,y;
        x=read();y=read();
        add(x,y);
        add(y,x);
    }
    for(int i=1;i<=n;i++)
        t[i]=read();
    dfs1(1,0);
    dfs2(1,1);
    maxx=n<<1;
    for(int i=1;i<=m;i++)
    {
        b[i]=read(),e[i]=read();
        lcaa[i]=lca(b[i],e[i]);
        update(root[b[i]],1,maxx,deep[b[i]]+n,1);
        update(root[fa[lcaa[i]]],1,maxx,deep[b[i]]+n,-1);
    }
    dfs3(1);
    cnt=0;
    memset(root,0,sizeof(root));
    memset(sum,0,sizeof(sum));
    memset(lson,0,sizeof(lson));
    memset(rson,0,sizeof(rson));
    for(int i=1;i<=m;i++)
    {
        update(root[e[i]],1,maxx,n-deep[b[i]]+2*deep[lcaa[i]],1);
        update(root[lcaa[i]],1,maxx,n-deep[b[i]]+2*deep[lcaa[i]],-1);
    }
    dfs4(1);
    for(int i=1;i<n;i++)
        printf("%d ",ans[i]);
    printf("%d",ans[n]);
    return 0;
}