hdu 4605 Magic Ball Game
2013-08-13 00:45
337 查看
题意:有T组测试数据,N表示这棵树有N个点,下一行的N个数,表示每个点的权值W,M表示边的关系,接下来的M行,每行有三个数字,u,b,b,表示点a和点b分别是点u的左儿子和右儿子。Q表示查询数,接下来的Q行,每行两个数字,v和X。
一个权值为X球从根节点开始下落,每落到一个节点的时候,1.如果X=W[i],或者没有儿子节点了,球停止下落。2.如果X<W[i],球各有1/2的概率落到左右儿子节点。3.如果X>W[i],球有1/8的概率落到左儿子,有7/8的概率落到右儿子。问球落到点v的概率是多少(概率用7^x/2^y表示,即输出x和y就可以)?
当知道点v的时候,我们要统计的是,从根节点到点v上有多少个节点权值是大于X的,有多少个节点权值是小于X的(并且分别是在左儿子还是右儿子),是否有节点的权值与X相等。用两棵树状数组维护(代表是在左儿子还是在右儿子),直接DFS一次,将DFS路径上的权值加入对应线状数组里,然后统计就可以了。
一个权值为X球从根节点开始下落,每落到一个节点的时候,1.如果X=W[i],或者没有儿子节点了,球停止下落。2.如果X<W[i],球各有1/2的概率落到左右儿子节点。3.如果X>W[i],球有1/8的概率落到左儿子,有7/8的概率落到右儿子。问球落到点v的概率是多少(概率用7^x/2^y表示,即输出x和y就可以)?
当知道点v的时候,我们要统计的是,从根节点到点v上有多少个节点权值是大于X的,有多少个节点权值是小于X的(并且分别是在左儿子还是右儿子),是否有节点的权值与X相等。用两棵树状数组维护(代表是在左儿子还是在右儿子),直接DFS一次,将DFS路径上的权值加入对应线状数组里,然后统计就可以了。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <map> #include <algorithm> using namespace std; const int N=1e5+5; #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) struct OP { int w,idx; OP(){} OP(int w,int idx) : w(w),idx(idx) {} }; struct BIT { int T[N*2],LIM; void init(int n) { LIM=n; memset(T,0,sizeof(T)); } int lowbit(int x){return x&(-x);} void updata(int pos,int valu) { for(int i=pos;i<=LIM;i+=lowbit(i)) T[i]+=valu; } int query(int st,int ed) { int sum=0; for(int i=ed;i>0;i-=lowbit(i)) sum+=T[i]; for(int i=st-1;i>0;i-=lowbit(i)) sum-=T[i]; return sum; } }seg[2]; int n,m,K; int W ,len,adj [2]; int ans1 ,ans2 ; map<int,int> H; vector<int> Y; vector<OP> op ; void fun(int u) { for(int i=0;i<(int)op[u].size();i++) { int id=H[ op[u][i].w ],idx=op[u][i].idx; ans1[idx]=ans2[idx]=0; if(seg[0].query(id,id)||seg[1].query(id,id)) ans1[idx]=-1; else { ans2[idx]+=seg[0].query(1,id)*3; ans2[idx]+=seg[0].query(id,len); int tmp=seg[1].query(1,id); ans1[idx]+=tmp; ans2[idx]+=tmp*3; ans2[idx]+=seg[1].query(id,len); } } } void dfs(int u) { int id=H[W[u]]; for(int i=0;i<2;i++) { int v=adj[u][i]; if(v==-1) break; seg[i].updata(id,1); fun(v); dfs(v); seg[i].updata(id,-1); } } int main() { //freopen("06.in","r",stdin); int t; scanf("%d",&t); while(t--) { scanf("%d",&n); Y.clear(); H.clear(); for(int i=1;i<=n;i++) { op[i].clear(); adj[i][0]=adj[i][1]=-1; scanf("%d",&W[i]); Y.push_back(W[i]); } scanf("%d",&m); for(int i=0;i<m;i++) { int u,a,b; scanf("%d%d%d",&u,&a,&b); adj[u][0]=a; adj[u][1]=b; } scanf("%d",&K); for(int i=0;i<K;i++) { int v,w; scanf("%d%d",&v,&w); Y.push_back(w); op[v].push_back(OP(w,i)); } sort(Y.begin(),Y.end()); Y.erase( unique(Y.begin(),Y.end()),Y.end()); for(int i=0;i<(int)Y.size();i++) H[Y[i]]=i+1; len=(int)Y.size(); seg[0].init(len+5); seg[1].init(len+5); fun(1); dfs(1); for(int i=0;i<K;i++) { if(ans1[i]==-1) puts("0"); else printf("%d %d\n",ans1[i],ans2[i]); } } return 0; }
相关文章推荐
- HDU 4605 Magic Ball Game 树上主席树
- HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)
- hdu 4605 Magic Ball Game
- hdu 4605 Magic Ball Game(可持久化笛卡尔树)
- HDU 4605 Magic Ball Game (dfs+离线树状数组)
- hdu-4605-Magic Ball Game-线段树+离线操作
- HDU 4605 Magic Ball Game 解题报告
- HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)
- hdu 4605-Magic Ball Game(树状数组)
- HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)
- hdu 4605:Magic Ball Game(主席树或者离线)
- 2013 多校联合 F Magic Ball Game (hdu 4605)
- hdu 4605 Magic Ball Game(主席树学习第二弹)
- 2013 多校联合 F Magic Ball Game (hdu 4605)
- hdu 4605 Magic Ball Game
- Magic Ball Game - HDU 4605 树状数组
- 2013 多校第一场 hdu 4605 Magic Ball Game
- HDU-4605 Magic Ball Game 树状数组+离散+dfs
- hdu-4605 Magic Ball Game[离散化+回溯+树状数组]
- HDU 4605 Magic Ball Game 树状数组