• LOJ#2665 树的计数


    题意:给你DFS序和BFS序,求树的期望高度。

    解:先分析性质。

    考虑到BFS序是分层的,DFS序的子树是一段,那么我们遍历BFS序并在DFS序上标记对应点的话,就会发现BFS序每一层都会把若干棵子树每个都分成若干个小子树,且换层的时候一定会是DFS序上第一个非空位置。

    设每个点的期望深度为hi,那么就是要求BFS序最后一个点的h。考虑每个点的深度怎么算。如果当前点不是新一层的开头,那么它的h一定等于他在BFS序前面一个点的深度。如果是开头,那么就要等于它父亲的深度 + 1,我们可以在DFS序上把每个点的子树染色以查明该点的父亲。如果这两种情况都有可能,那么h就是这两种情况的平均数。

    考虑什么时候只可能是一种情况。

    当这个点在DFS序上的位置前于BFS序上前一个点在DFS序上的位置的时候,当前点一定是新一层的开头。

    当这个点在DFS序上的位置后与BFS序上前一个点在DFS序上的位置的时候:如果这个点和BFS上前一个点在DFS序上的位置不相邻,那么这两个点一定在同一层。

    相邻的时候,如果当前点在DFS序的前面还有空位,那么一定在同一层。否则考虑这个子树后面还有没有空位,如果有也一定在同一层,因为要换层的话一定要把后面的每个都走一遍。

    实现的时候就用线段树维护颜色和区间和。

      1 #include <bits/stdc++.h>
      2 
      3 const int N = 200010;
      4 
      5 int col[N << 2], sum[N << 2];
      6 int d[N], b[N], pos[N];
      7 double h[N];
      8 
      9 inline void pushdown(int o) {
     10     if(!col[o]) return;
     11     col[o << 1] = col[o << 1 | 1] = col[o];
     12     col[o] = 0;
     13     return;
     14 }
     15 
     16 void add(int p, int l, int r, int o) {
     17     if(l == r) {
     18         sum[o] = 1;
     19         return;
     20     }
     21     int mid = (l + r) >> 1;
     22     if(p <= mid) add(p, l, mid, o << 1);
     23     else add(p, mid + 1, r, o << 1 | 1);
     24     sum[o] = sum[o << 1] + sum[o << 1 | 1];
     25     return;
     26 }
     27 
     28 int getSum(int L, int R, int l, int r, int o) {
     29     if(L <= l && r <= R) return sum[o];
     30     int mid = (l + r) >> 1, ans = 0;
     31     if(L <= mid) ans += getSum(L, R, l, mid, o << 1);
     32     if(mid < R) ans += getSum(L, R, mid + 1, r, o << 1 | 1);
     33     return ans;
     34 }
     35 
     36 void change(int L, int R, int v, int l, int r, int o) {
     37     if(L <= l && r <= R) {
     38         col[o] = v;
     39         return;
     40     }
     41     pushdown(o);
     42     int mid = (l + r) >> 1;
     43     if(L <= mid) change(L, R, v, l, mid, o << 1);
     44     if(mid < R) change(L, R, v, mid + 1, r, o << 1 | 1);
     45     return;
     46 }
     47 
     48 int ask(int p, int l, int r, int o) {
     49     if(l == r) return col[o];
     50     int mid = (l + r) >> 1;
     51     pushdown(o);
     52     if(p <= mid) return ask(p, l, mid, o << 1);
     53     else return ask(p, mid + 1, r, o << 1 | 1);
     54 }
     55 
     56 int getKth(int k, int l, int r, int o) {
     57     if(l == r) {
     58         return r + (k > sum[o]);
     59     }
     60     int mid = (l + r) >> 1;
     61     if(k <= sum[o << 1]) {
     62         return getKth(k, l, mid, o << 1);
     63     }
     64     else {
     65         return getKth(k - sum[o << 1], mid + 1, r, o << 1 | 1);
     66     }
     67 }
     68 
     69 int main() {
     70 
     71     int n;
     72     scanf("%d", &n);
     73     for(int i = 1; i <= n; i++) {
     74         scanf("%d", &d[i]);
     75         pos[d[i]] = i;
     76     }
     77     for(int i = 1; i <= n; i++) {
     78         scanf("%d", &b[i]);
     79     }
     80     /// h[1] = 1
     81     for(int i = 1; i <= n; i++) {
     82         /// b[i] in pos[b[i]]
     83         int p = pos[b[i]], lastp = pos[b[i - 1]];
     84         add(p, 1, n, 1);
     85         int s = getSum(1, p, 1, n, 1);
     86         int ed = getKth(s + 1, 1, n, 1) - 1;
     87         /// [p, ed]
     88         if(i == 1) {
     89             h[b[i]] = 1;
     90         }
     91         else if(p == lastp + 1 && s == p && (ed < n ? getSum(ed + 1, n, 1, n, 1) : 0) == n - ed) {
     92             int fr = ask(p, 1, n, 1);
     93             if(fr != d[1]) h[b[i]] = (h[fr] + 1 + h[b[i - 1]]) / 2;
     94             else h[b[i]] = h[fr] + 1;
     95         }
     96         else if(p < lastp) { /// new line
     97             int fr = ask(p, 1, n, 1);
     98             h[b[i]] = h[fr] + 1;
     99         }
    100         else {
    101             h[b[i]] = h[b[i - 1]];
    102         }
    103         change(p, ed, b[i], 1, n, 1);
    104     }
    105 
    106     printf("%.3f
    ", h[b[n]]);
    107     return 0;
    108 }
    AC代码
  • 相关阅读:
    H5调用Android播放视频
    JavaScript调Java
    Java调用JavaScript
    python的下载和安装
    s5_day1作业
    s5_day2作业
    pycharm激活(转)
    for…else和while…else
    小练习
    09 grep、正则表达式和sed
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10775260.html
Copyright © 2020-2023  润新知