zoukankan      html  css  js  c++  java
  • p1652

    乱搞大法好!什么树的dfs序+线段树都是辣鸡.

    这道题看似很难,但是它给了每个人的回房顺序,那么就好搞很多.

    先存起来每个房间进入的时间和每个人进入的顺序,然后直接dfs.

    根据dfs的性质当前一定只通过这个房间所在的一条路直接下来,那么只要求出这个过程中时间比自己小的就好,我们想到了再用一个高级数据结构存一下.这个过程相当于求前缀和了,可以上一个树状数组,比线段树好写无数倍.

    总结一下:记录i房间进入时间t[i]和第i个人进入的房间num[i].dfs的时候now节点的答案ans[now]=sum(t[now]),然后再add(t[now],1),找节点中没走过的去dfs,完了之后再add(t[now],-1);

    using namespace std;
    inline int lowbit(int x){
        return x&(-x);
    }
    struct edge{
        int x,y;
        int next;
    }e[1000010];
    int head[100010],tot;
    int i,tx,ty;
    int n;
    int t[100010],v[100010],ans[100010],num[100010],c[100010];
    inline void add(int x,int y){
        tot++;
        e[tot].x=x;
        e[tot].y=y;
        e[tot].next=head[x];
        head[x]=tot;
        return ;
    }
    inline void jia(int x){
        for(;x<=n;x+=lowbit(x))
            c[x]++;
    }
    
    inline void jian(int x){
        for(;x<=n;x+=lowbit(x))
            c[x]--;
    }
    inline int sum(int x){
        int asd=0;
        for(;x;x-=lowbit(x))
            asd+=c[x];
        return asd;
    }
    inline void dfs(int now){
        v[now]=1;
        ans[now]=sum(t[now]);
        jia(t[now]);
        for(int j=head[now];j;j=e[j].next)
            if(!v[e[j].y])
                dfs(e[j].y);
        jian(t[now]);
        return ;
    }
    int main(){
        n=read();
        for(i=1;i<n;i++){
            tx=read();ty=read();
            add(tx,ty);
            add(ty,tx);
        }
        for(i=1;i<=n;i++){
            num[i]=read();
            t[num[i]]=i;
        }
        dfs(1);
        for(i=1;i<=n;i++)
            write(ans[num[i]]),putchar(10);
    }
  • 相关阅读:
    学习笔记—二进制和精度问题
    学习笔记—Buffer的常用方法与实现
    学习笔记—Node中第三方模块
    学习笔记—npm的介绍与使用
    .NET中序列化(一)
    .NET中序列化(二)
    JavaScript在多浏览器下杂谈1for循环
    .NET中序列化(三)
    DLCB额度切分
    DLCB解决问题的思路
  • 原文地址:https://www.cnblogs.com/qywyt/p/9799954.html
Copyright © 2011-2022 走看看