zoukankan      html  css  js  c++  java
  • 洛谷P2982 [USACO10FEB]慢下来Slowing down

    题目

    • 题目大意 :给出一棵树,节点有点权,求每个节点的祖先中点权小于该节点的结点的个数 。

    • 思路如下 :

      • 从根节点开始,对树进行深度优先遍历。

      • 当进行到节点 i 时,有:
        •  $ ext{i}$ ​的祖先们 ​$ ext{Father[i]}$ 已经被访问过了,但还没有退出。

        • 其他节点或者已经被访问过并退出了,或者还没有被访问。

      • 那么需要一个数据结构,维护那些已经被访问过了,但还没有退出的点权,支持查询小于特定值的元素的数量

      • 可以使用树状数组或者线段树

    • Code

    • #include <cstdio>
      #include <cstring>
      #define re register
      #define GC getchar()
      #define Clean(X,K) memset(X,K,sizeof(X))
      #define Lowbit(X) (X&(-X))
      int Qread () {
          int X = 0 ;    char C = GC ;
          while (C > '9' || C < '0') C = GC ;
          while (C >='0' && C <='9') {
              X = X * 10 + C - '0' ;
              C = GC ;
          }
          return X ;
      }
      const int Maxn = 100005 ;
      int N ,  P_C[Maxn] , Ans[Maxn] , En = 0 , Head[Maxn] , T[Maxn];
      struct Edge {
          int From_Where , Goto_Where , Next_Edge ;
      };
      Edge E[Maxn * 2] ;
      void Adg (int X , int Y) {
          E[++En].From_Where = X ;
          E[En].Goto_Where = Y ;
          E[En].Next_Edge = Head[X] ;
          Head[X] = En ;
      }
      void Add (int X , int K) {
          while (X <= N) {
              T[X] += K ;
              X += Lowbit(X) ;
          }
      }
      int Ask (int X) {
          int Ans = 0 ;
          while (X > 0) {
              Ans += T[X] ;
              X -= Lowbit(X) ;
          }
          return Ans ;
      }
      void Super_Powerful_DFS (int X , int Lst) {
          Ans[P_C[X]] = Ask (P_C[X]) ;
          //printf ("%d %d %d
      " , X , P_C[X],Ans[P_C[X]]) ;
          Add (P_C[X] , 1) ;
          for (re int i = Head[X] ; i ; i = E[i].Next_Edge ) {
              if (E[i].Goto_Where == Lst) continue ;
              Super_Powerful_DFS ( E[i].Goto_Where , X) ;
          }
          Add (P_C[X] , -1) ;
      }
      int main () {
          //freopen ("P2982.in" , "r" , stdin) ;
          Clean (Ans , 0) , Clean (Head , 0) , Clean (T , 0) , En = 0 ;
          N = Qread () ;
          for (re int i = 1 ; i < N ; ++ i) {
              int X = Qread () , Y = Qread () ;
              Adg (X , Y) , Adg (Y , X) ;
          }
          for (re int i = 1 ; i <= N; ++ i) {
              int X = Qread () ;
              P_C[X] = i ;
          }
          Super_Powerful_DFS ( 1 , -1) ;
          for (re int i = 1 ; i <= N; ++ i) printf ("%d
      " , Ans[i]) ;
          fclose (stdin) ;
          fclose (stdout);
          return 0;
      }
      点击这里学习树状数组

    Thanks !

  • 相关阅读:
    BZOJ 1101 莫比乌斯函数+分块
    BZOJ 2045 容斥原理
    BZOJ 4636 (动态开节点)线段树
    BZOJ 2005 容斥原理
    BZOJ 2190 欧拉函数
    BZOJ 2818 欧拉函数
    BZOJ 3123 主席树 启发式合并
    812. Largest Triangle Area
    805. Split Array With Same Average
    794. Valid Tic-Tac-Toe State
  • 原文地址:https://www.cnblogs.com/bj2002/p/10432150.html
Copyright © 2011-2022 走看看