首页 > 代码库 > hdu 4605 Magic Ball Game (在线主席树/离线树状数组)

hdu 4605 Magic Ball Game (在线主席树/离线树状数组)

hdu 4605

题意:

  有一颗树,根节点为1,每一个节点要么有两个子节点,要么没有,每个节点都有一个权值wi 。然后,有一个球,附带值x 。

  球到达某个节点上,如果x==wi,那么球停在这个节点上 。当然,这个点是叶子节点也会停止 。

  如果x<wi,那么有1/2的概率走向左子树,有1/2的概率走向右子树 。

  如果x>wi,那么有1/8的概率走向左子树,有7/8的概率走向右子树 。

  问球经过v节点的概率 。(停在v节点也算)

解法:

  在线的话每一个节点建一棵根节点到该节点的线段树,离线的话就先把询问按DFS序排序,然后瞎搞搞就ok了 。。。

 

在线主席树

#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <queue>#include <set>#include <vector>#include <map>#define ll long longusing namespace std;const int N=100007;int Ls[N*20],Rs[N*20],cnt[N*20][2];int root[N],tot;int e[N][2];int w[N],sort_w[N];int n;inline int Hash(int x){    return upper_bound(sort_w+1,sort_w+n+1,x)-sort_w-1;}inline void init(){    tot=0;    memset(e,-1,sizeof(e));}inline int bulidtree(int L,int R){     int k=tot++;     cnt[k][0]=cnt[k][1]=0;     if (L==R) return k;     int mid=(L+R)>>1;     Ls[k]=bulidtree(L,mid);     Rs[k]=bulidtree(mid+1,R);     return k;}inline void copy(int x,int y){    Ls[x]=Ls[y];    Rs[x]=Rs[y];    cnt[x][0]=cnt[y][0];    cnt[x][1]=cnt[y][1];}// to 0 左子树  1 右子树inline int update(int o,int p,int to,int L,int R){    int k=tot++;    copy(k,o);    cnt[k][to]++;    if (L==R) return k;    int mid=(L+R)>>1;    if (p<=mid) Ls[k]=update(Ls[k],p,to,L,mid);    else Rs[k]=update(Rs[k],p,to,mid+1,R);    return k;}inline int query(int o,int x,int y,int to,int L,int R){    if (x>y) return 0;    if (L==x && R==y) return cnt[o][to];    int mid=(L+R)>>1;    if (y<=mid) return query(Ls[o],x,y,to,L,mid);    else if (x>mid) return query(Rs[o],x,y,to,mid+1,R);    else return query(Ls[o],x,mid,to,L,mid)+query(Rs[o],mid+1,y,to,mid+1,R);}inline void dfs(int u){    for (int i=0;i<=1;i++) if (~e[u][i]) {        int v=e[u][i];        root[v]=update(root[u],Hash(w[u]),i,1,n);        dfs(v);    }}int main(){    int t,m,q;    scanf("%d",&t);    while (t--){        init();        scanf("%d",&n);        for (int i=1;i<=n;i++) {            scanf("%d",&w[i]);            sort_w[i]=w[i];        }        sort(sort_w+1,sort_w+n+1);        scanf("%d",&m);        while (m--){            int u,a,b;            scanf("%d %d %d",&u, &a, &b);            e[u][0]=a;            e[u][1]=b;        }        root[1]=bulidtree(1,n);        dfs(1);        scanf("%d",&q);        while (q--){            int v,x;            scanf("%d %d",&v,&x);            int id=Hash(x);            if (x==sort_w[id]){                if (query(root[v],id,id,0,1,n) || query(root[v],id,id,1,1,n)){                    puts("0");                    continue;                }            }                        int L_down=query(root[v],1,id,0,1,n);            int L_up=query(root[v],id+1,n,0,1,n);            int R_down=query(root[v],1,id,1,1,n);            int R_up=query(root[v],id+1,n,1,1,n);            printf("%d %d\n",R_down,L_up+R_up+3*L_down+3*R_down);        }    }    return 0;}

 

离线树状数组

  1 #include <iostream>  2 #include <cstdio>  3 #include <algorithm>  4 #include <cmath>  5 #include <cstring>  6 #include <queue>  7 #include <set>  8 #include <vector>  9 #include <map> 10 #define ll long long 11  12 using namespace std; 13  14 const int N=100007; 15  16 int w[N],e[N][2]; 17 int sort_w[N]; 18 int c[N][2];  // 树状数组  19 int n,Q; 20 int pos[N]; 21 int ans[N][2]; 22  23 struct QUERY{ 24     int v,x,id; 25     int s; 26     bool operator < (const QUERY & t) const { 27         return s<t.s; 28     } 29 }q[N]; 30  31 inline int Hash(int x){ 32     return upper_bound(sort_w+1,sort_w+n+1,x)-sort_w-1; 33 } 34  35 inline void init(){ 36     memset(c,0,sizeof(c)); 37     memset(e,0,sizeof(e)); 38 }     39  40 inline int lowbit(int x){ 41     return x&(-x); 42 } 43  44 inline void add(int x,int d,int to){ 45     while (x<=n){ 46         c[x][to]+=d; 47         x+=lowbit(x); 48     } 49 } 50  51 inline int sum(int x,int to){ 52     int ret=0; 53     while (x){ 54         ret+=c[x][to]; 55         x-=lowbit(x); 56     } 57     return ret; 58 } 59  60 inline int query(int L,int R,int to){ 61     return sum(R,to)-sum(L-1,to); 62 } 63  64 int cnt; 65 inline void dfs1(int u){ 66     pos[u]=++cnt; 67     for (int i=0;i<=1;i++) if (e[u][i]) 68         dfs1(e[u][i]); 69 } 70  71 inline void dfs2(int u){ 72     while (cnt<=Q && q[cnt].v==u){ 73         int id=Hash(q[cnt].x); 74         if (sort_w[id]==q[cnt].x){ 75             if (query(id,id,0) || query(id,id,1)){ 76                 ans[q[cnt].id][0]=-1; 77                 cnt++; 78                 continue; 79             } 80         } 81  82         int L_down=query(1,id,0); 83         int L_up=query(id+1,n,0); 84         int R_down=query(1,id,1); 85         int R_up=query(id+1,n,1); 86  87         ans[q[cnt].id][0]=R_down; 88         ans[q[cnt].id][1]=L_up+R_up+3*L_down+3*R_down; 89         cnt++; 90     } 91  92     int id=Hash(w[u]); 93     for (int i=0;i<=1;i++) if (e[u][i]) { 94         add(id,1,i); 95         dfs2(e[u][i]); 96         add(id,-1,i); 97     } 98 } 99 100 int main(){101     int t,m;102     scanf("%d",&t);103     while (t--){104         init();105 106         scanf("%d",&n);107         for (int i=1;i<=n;i++) {108             scanf("%d",&w[i]);109             sort_w[i]=w[i];110         }111         sort(sort_w+1,sort_w+n+1);112 113         scanf("%d",&m);114         for (int i=1;i<=m;i++){115             int u,a,b;116             scanf("%d %d %d",&u, &a, &b);117             e[u][0]=a;118             e[u][1]=b;119         }120         121         scanf("%d",&Q);122         for (int i=1;i<=Q;i++){123             scanf("%d%d",&q[i].v,&q[i].x);124             q[i].id=i;125         }126 127         cnt=1;128         dfs1(1);129 130         for (int i=1;i<=Q;i++) q[i].s=pos[q[i].v];131         sort(q+1,q+Q+1);132 133         cnt=1;134         dfs2(1);135 136         for (int i=1;i<=Q;i++){137             if (~ans[i][0]) printf("%d %d\n",ans[i][0],ans[i][1]);138             else puts("0");139         }140     }141 142     return 0;143 }

 

hdu 4605 Magic Ball Game (在线主席树/离线树状数组)