hdu-4605 Magic Ball Game[离散化+回溯+树状数组]

来源:互联网 发布:汉王考勤软件下载 编辑:程序博客网 时间:2024/06/15 05:34
题目大意很简单。

有一颗树(10^5结点),所有结点要么没有子结点,要么有两个子结点。
然后每个结点都有一个重量值,根结点是1

然后有一个球,从结点1开始往子孙结点走。

每碰到一个结点,有三种情况

如果此球重量等于该结点重量,球就停下了

如果此球重量小于该结点重量,则分别往左右儿子走的可能都是1/2

如果此球重量大于该结点重量,则走向左儿子的概率是1/8,右儿子的概率是7/8

然后若干个询问(10^5次),问一个重量为x的球经过结点v的概率


对于从v到根节点(不包括v),假如我们知道 ls (向左走比x小的节点个数)、rs(向右走比x小的节点个数)、lb(向左走比x大的节点个数)、rb(向右走比x大的节点的个数)

那么概率就是 c= (1/2)^ls * (1/8)*lb * (1/2) ^ rs * (7/8)^rb转换成题目要求的输出就是 a=rs,b=3*(rs+ls)+lb+rb;

离线做法:

要求得上述值。可以搜索整颗树,到v点时处理对v点的查询。还需要记录v到root路径上的节点状态,所以要回溯。还需要快速求的从v到根的路径上向左 和 向右 的 重量区间的节点出现个数,就可以用树状数组记录每个重量区间包含多少个节点,因为重量范围很大,所以需要离散化。

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <vector>#include <algorithm>using namespace std;const int maxn=100008;int n,q,size;int v[maxn*2];//节点数值int sub_v[maxn*2];int dv[maxn*2];//节点离散化后的数值int lbit[maxn*4];//bit处理向左走的节点值域int rbit[maxn*4];//bit处理向右走的节点值域int X[maxn];int Y[maxn];vector<int> query[maxn];//节点的查询vector<int> g[maxn];//树节点void add_edge(int u,int v){g[u].push_back(v);}void init(){for(int i=0;i<maxn;++i){g[i].clear();query[i].clear();}}void init_bit(){memset(lbit,0,sizeof(lbit));memset(rbit,0,sizeof(rbit));}int lowbit(int x){return x&(-x);}void add(int k,int num,int which){while(k<=size){if(!which) lbit[k]+=num;else rbit[k]+=num;k+=lowbit(k);}}int read(int k,int which){int sum=0;while(k){if(!which)sum+=lbit[k];else sum+=rbit[k];k-=lowbit(k);}return sum;}void dfs(int u,int lct,int rct){for(int i=0;i<query[u].size();++i){int num=query[u][i],x=dv[n+num];// printf("%d\n", read(x,0)-read(x-1,0));// printf("%d\n", read(x,1)-read(x-1,1));if((read(x,0)-read(x-1,0))||(read(x,1)-read(x-1,1))){X[num]=-1;continue;}int ls=read(x,0),rs=read(x,1);int lb=read(size,0)-read(x,0),rb=read(size,1)-read(x,1);X[num]=rs,Y[num]=3*(rs+ls)+lb+rb;}if(g[u].size()){int dt=dv[u];//向左移动add(dt,1,0),dfs(g[u][0],lct+1,rct),add(dt,-1,0);//向右移动add(dt,1,1),dfs(g[u][1],lct,rct+1),add(dt,-1,1);}}void discretize(){int _n=n+q;for(int i=1;i<=_n;++i)sub_v[i]=v[i];sort(sub_v+1,sub_v+_n+1);size=unique(sub_v+1,sub_v+_n+1)-sub_v-1;for(int i=1;i<=_n;++i)dv[i]=lower_bound(sub_v+1,sub_v+size+1,v[i])-sub_v;}void solve(){init_bit();discretize();dfs(1,0,0);for(int i=1;i<=q;++i){if(X[i]==-1)printf("0\n");else printf("%d %d\n",X[i],Y[i]);}}int main(){int t;scanf("%d",&t);while(t--){init();scanf("%d",&n);for(int i=1;i<=n;++i)scanf("%d",v+i);int m,u,a,b;scanf("%d",&m);for(int i=0;i<m;++i){scanf("%d%d%d",&u,&a,&b);add_edge(u,a),add_edge(u,b);}int x,vn;scanf("%d",&q);for(int i=1;i<=q;++i){scanf("%d%d",&vn,&x);v[n+i]=x;query[vn].push_back(i);}solve();}return 0;}


0 0
原创粉丝点击