HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)


分类: ACM_数据结构   833人阅读  评论(0)  收藏  举报

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

题意:给出一棵二叉树,每个结点孩子数目为0或者2。每个节点都有一个权值,初始在根,扔一个筛子,筛子的值与结点的权值大小关系影响往左往右的概率。

问给出筛子权值,问到达某个结点的概率。

http://acm.hdu.edu.cn/showproblem.php?pid=4605

做法:肯定需要统计每个点到根的路径中,有哪些结点是需要往左孩子走,哪些需要往右孩子走。然后 根据筛子权值,分别二分,就知道有多少个结点是什么概率。

对于每个结点维护一个set或者线段树是不可达的。

因此有了离线做法:离线处理之后,先处理父亲节点,再处理孩子节点,维护两个线段树或者set,保存到达这个节点,哪些是需要往左遍历,哪些需要往右。之后区间查询或者二分,就能统计个数。


在线做法:利用可持久性,对于每个结点维护一个线段树,就需要利用主席树。做法大致相似。


code : 主席树

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include <queue>  
  3. #include <algorithm>  
  4. #include <cstdio>  
  5. #include <cstring>  
  6. using namespace std;  
  7. typedef long long LL;  
  8. const int N = 200005;  
  9. const int M = 10000005;  
  10. struct Edge{  
  11.     int v,next,k;  
  12. }e[N];  
  13. int start[N], totaledge;  
  14. int T[M], lson[M], rson[M], lcnt[M], rcnt[M];  
  15. int w[N], n, tot, m, x[N], cnt;  
  16. queue<int> que;  
  17. void add(int u,int v,int k){  
  18.     e[totaledge].v = v;  
  19.     e[totaledge].k = k;  
  20.     e[totaledge].next = start[u];  
  21.     start[u] = totaledge ++;  
  22. }  
  23. int bulid (int l ,int r){  
  24.     int root = tot ++;  
  25.     lcnt[root] = rcnt[root] = 0;  
  26.     if(l == r){  
  27.         lcnt[root] = rcnt[root] = 0;  
  28.         return root;  
  29.     }  
  30.     int m = (l + r) >> 1;  
  31.     lson[root] = bulid(l , m);  
  32.     rson[root] = bulid(m + 1 , r);  
  33.     lcnt[root] = lcnt[lson[root]] + lcnt[rson[root]];  
  34.     rcnt[root] = rcnt[lson[root]] + rcnt[rson[root]];  
  35.     return root;  
  36. }  
  37. int update(int root,int l,int r, int pos, int lval, int rval) {  
  38.     int newroot = tot ++;  
  39.     lcnt[newroot] = rcnt[newroot] = 0;  
  40.     if(pos == l && pos == r){  
  41.         lcnt[newroot] = lcnt[root] + lval;  
  42.         rcnt[newroot] += rcnt[root] + rval;  
  43.         return newroot;  
  44.     }  
  45.     int m = (l + r) >> 1;  
  46.     if(pos <= m) {  
  47.         lson[newroot] = update(lson[root], l, m, pos, lval, rval);  
  48.         rson[newroot] = rson[root];  
  49.     }  
  50.     else {  
  51.         rson[newroot] = update(rson[root], m + 1, r, pos, lval, rval);  
  52.         lson[newroot] = lson[root];  
  53.     }  
  54.     lcnt[newroot] = lcnt[lson[newroot]] + lcnt[rson[newroot]];  
  55.     rcnt[newroot] = rcnt[lson[newroot]] + rcnt[rson[newroot]];  
  56.     return newroot;  
  57. }  
  58. int query(int root,int L,int R, int l,int r, int k){  
  59.     if (l > r ) return 0;  
  60.     if (l >= cnt) return 0;  
  61.     if (r < 0 ) return 0;  
  62.     if(L == l && R == r) {  
  63.         if(k == 0) return lcnt[root];  
  64.         return rcnt[root];  
  65.     }  
  66.     int m = (L + R) >> 1;  
  67.     if(r <= m) return query(lson[root], L, m, l, r, k);  
  68.     else if(l > m) return query(rson[root], m + 1, R, l, r, k);  
  69.     else return query(lson[root], L ,m , l , m, k) + query(rson[root], m + 1, R, m + 1 ,r, k);  
  70. }  
  71. int main() {  
  72.     int t;  
  73.     scanf ("%d", &t);  
  74.     while (t--) {  
  75.         tot = 0;  
  76.         totaledge = 0;  
  77.         memset (start , -1 , sizeof(start));  
  78.         scanf ("%d", &n);  
  79.         for (int i = 1 ; i <= n ; i ++) {  
  80.             scanf ("%d", &w[i]);  
  81.             x[i - 1] = w[i];  
  82.         }  
  83.         sort (x, x+n);  
  84.         cnt = unique(x, x + n) - x;  
  85.         x[cnt] = -1;  
  86.         T[1] = bulid(0, cnt - 1);  
  87.         scanf ("%d", &m);  
  88.         for (int i = 0 ; i < m ; i++){  
  89.             int u , a , b;  
  90.             scanf("%d%d%d", &u, &a, &b);  
  91.             add(u , a, 0);  
  92.             add(u , b, 1);  
  93.         }  
  94.         que.push(1);  
  95.         while(!que.empty()) {  
  96.             int u = que.front();  
  97.             que.pop();  
  98.             for (int i = start[u] ; i != -1 ; i = e[i].next) {  
  99.                 int v = e[i].v, k = e[i].k;  
  100.                 T[v] = update(T[u], 0, cnt - 1, lower_bound(x, x + cnt , w[u]) - x , k == 0 , k == 1);  
  101.                 que.push(v);  
  102.             }  
  103.         }  
  104.         int q;  
  105.         scanf ("%d", &q);  
  106.         while(q --){  
  107.             int num, v;  
  108.             scanf ("%d%d", &v, &num);  
  109.             if(v == 1){  
  110.                 printf("0 0\n");  
  111.                 continue;  
  112.             }  
  113.             int p = lower_bound(x, x + cnt , num) - x;  
  114.             int l = p - 1 , r = p ;  
  115.             if(x[p] == num){  
  116.                 int ret = query(T[v], 0 , cnt - 1, p, p, 0) + query(T[v], 0 , cnt - 1 , p, p, 1);  
  117.                 if(ret){  
  118.                     puts("0");  
  119.                     continue;  
  120.                 }  
  121.                 r ++ ;  
  122.             }  
  123.             int left_small = query(T[v],0 , cnt - 1, 0, l, 0);  
  124.             int left_large = query(T[v],0 , cnt - 1, r , cnt - 1, 0);  
  125.             int right_small = query(T[v],0 , cnt - 1, 0, l, 1);  
  126.             int right_large = query(T[v],0 , cnt - 1, r , cnt - 1, 1);  
  127.             int down = 0, up = 0;  
  128.             // cout<<left_small<<" "<<left_large<<" "<<right_small<<" "<<right_large<<endl;  
  129.             down += left_small * 3;  
  130.             down += left_large;  
  131.             down += right_small * 3;  
  132.             up += right_small;  
  133.             down += right_large;  
  134.             printf("%d %d\n",up,down);  
  135.         }  
  136.     }  
  137.     return 0;  
  138. }     

你可能感兴趣的:(ACM_数据结构)