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


    题目:

    洛谷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
    ",ask(0,1,n,in[p[i]],in[p[i]]));
            add(0,1,n,in[p[i]],out[p[i]],1);
        }
        return 0;
    } 
    
  • 相关阅读:
    数独游戏技巧(转)
    Strange Way to Express Integers(中国剩余定理+不互质)
    C Looooops(poj2115+扩展欧几里德)
    X问题(中国剩余定理+不互质版应用)hdu1573
    合并果子(优先队列 +或者+哈夫曼)
    Shaping Regions(dfs)
    Modular Inverse(zoj3609+欧几里德)
    Contest2075
    Clock Pictures(kmp + Contest2075
    Opening Ceremony(贪心)
  • 原文地址:https://www.cnblogs.com/zyt1253679098/p/8797597.html
Copyright © 2020-2023  润新知