• 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);
    }
  • 相关阅读:
    内存寻址:逻辑地址到物理地址的转化
    变量类型,变量作用域,变量存储空间,变量生命周期
    位运算计算与位运算应用
    sizeof()计算
    位域(位段)
    自然对齐和强制对齐
    内存中的数据对齐
    用汇编编写子程序,可以显示字符串到屏幕指定位置
    汇编语言 实验9 根据材料编程
    80x25彩色字符模式
  • 原文地址:https://www.cnblogs.com/qywyt/p/9799954.html
Copyright © 2020-2023  润新知