【洛谷2982】[Usaco2010 Feb]慢下来Slowdown(dfs序+线段树)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hqddm1253679098/article/details/78819594

题目:洛谷2982


分析:

这道题最重要的是想明白一点:牛i走到以后只对P_i的子树产生影响

知道这个以后,就可以想到在线维护每个牧场已经被“影响”了多少次(也就是在此之前有多少个牛是到达自己的祖先结点的),这就是从谷仓到这个牧场需要减速多少次。

怎么维护子树信息呢?dfs序+线段树啊……

于是变成模板题


代码:

(虽然题目只要求支持单点查询,但是线段树模板打顺手了就不知不觉地写了区间查询……)

in[i]代表i的编号

out[i]代表i子树中最后一个结点的编号

in[i]~out[i]就是结点i和它的子树

#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;
vector<int>g[100010];
int in[100010],out[100010],p[100010],n,cnt,ans;
struct node
{
    int val;
    int lazy;
}tree[400010];

void dfs(int u,int fa)
{
    in[u]=++cnt;
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        if(v==fa)continue;
        dfs(v,u);
    }
    out[u]=cnt;
}

void pushdown(int root,int lt,int rt)
{
    if(tree[root].lazy==0)return;
    int mid=(lt+rt)/2;
    node &ln=tree[root*2+1],&rn=tree[root*2+2];
    ln.val+=tree[root].lazy*(mid-lt+1);
    ln.lazy+=tree[root].lazy;
    rn.val+=tree[root].lazy*(rt-mid);
    rn.lazy+=tree[root].lazy;
    tree[root].lazy=0;
}
void add(int root,int lt,int rt,int ls,int rs,int x)
{
    if(lt>rt||lt>rs||rt<ls)return;
    if(lt>=ls&&rt<=rs)
        tree[root].val+=x*(rt-lt+1),
        tree[root].lazy+=x;
    else 
    {
        int mid=(lt+rt)/2;
        pushdown(root,lt,rt);
        add(root*2+1,lt,mid,ls,rs,x);
        add(root*2+2,mid+1,rt,ls,rs,x);
        tree[root].val=tree[root*2+1].val+tree[root*2+2].val;
    }
}
int ask(int root,int lt,int rt,int ls,int rs)
{
    if(lt>rt||lt>rs||rt<ls)return 0;
    if(lt>=ls&rt<=rs)
        return tree[root].val;
    else
    {
        int mid=(lt+rt)/2;
        pushdown(root,lt,rt);
        return ask(root*2+1,lt,mid,ls,rs)+ask(root*2+2,mid+1,rt,ls,rs);
    }
}
int main(void)
{
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b); 
        g[a].push_back(b);
        g[b].push_back(a);
    }
    for(int i=1;i<=n;i++)
        scanf("%d",p+i);
    dfs(1,0);
    for(int i=1;i<=n;i++)
    {
        printf("%d\n",ask(0,1,n,in[p[i]],in[p[i]]));
        add(0,1,n,in[p[i]],out[p[i]],1);
    }
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/hqddm1253679098/article/details/78819594