hdu 4605 Magic Ball Game(离线+树状数组)
来源:互联网 发布:开发游戏的软件 编辑:程序博客网 时间:2024/05/17 19:57
题意:有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就可以)?
以上复制与shiqi_614大牛关于这道题的描述。
做法我研究了许久才弄懂,一开始直接用线段树的结构去从那个点往上走,后来发觉这不是一个完全二叉树。。
做法是把树的每条链用树状数组去维护,DFS这颗树,用一种类似回朔的办法。对于权值离散化,我用的是map映射,走到某个节点,如果要往左边走,就把这个节点权值加1加入第一颗树状数组,往右走就加入第二颗,如果当前节点有询问,直接用lower_bound找到>=x的第一个值如果这个值等于x且sum(pos,0)-sum(pos-1,0)或者sum(pos,1)-sum(pos-1,1)>=1那么就说明这条链上有等于x的,就不可达到。不然就统计前缀和,代表前面有几个小于x的值,以及可以算出后面有几个大于x的值,然后计算既可。
AC代码:
#pragma comment(linker, "/STACK:102400000,102400000")#include<cstdio>#include<ctype.h>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdlib>#include<stack>#include<cmath>#include<queue>#include<set>#include<map>#include<ctime>#include<string.h>#include<string>#include<bitset>using namespace std;#define ll __int64#define eps 1e-8#define NMAX 100000+10template<class T>inline void scan_d(T &ret){ char c; int flag = 0; ret=0; while(((c=getchar())<'0'||c>'9')&&c!='-'); if(c == '-') { flag = 1; c = getchar(); } while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); if(flag) ret = -ret;}int w[NMAX],a[2][NMAX],G[NMAX][2],wei[NMAX],nct,ans[NMAX][2];map<int,int>mp;vector<pair<int, int > >v[NMAX];int lowbit(int x){ return x&(-x);}int sum(int x, int flag){ int ret = 0; while(x > 0) { ret += a[flag][x]; x -= lowbit(x); } return ret;}void add(int x, int d, int flag){ while(x <= nct) { a[flag][x] += d; x += lowbit(x); }}map<int,int>::iterator it;void dfs(int pos){ int sz = v[pos].size(); for(int i = 0; i < sz; i++) { int x = v[pos][i].second,k = v[pos][i].first,pp; it = mp.lower_bound(x);//第一个>=x的 if(it == mp.end()) pp = nct+1; else pp = it->second; int t1 = sum(pp,0)-sum(pp-1,0),t2 = sum(pp,1)-sum(pp-1,1); if(it->first == x && (t1 >= 1 || t2 >= 1)) { ans[k][0] = -1; continue; } t1 = sum(pp-1,0); t2 = sum(pp-1,1); int t3 = sum(nct,0)-t1, t4 = sum(nct,1)-t2;// cout<<x<<" "<<pp<<" "<<t1<<" "<<t2<<" "<<t3<<" "<<t4<<endl; ans[k][0] = t2; ans[k][1] = 3*t1+3*t2+t3+t4; } if(G[pos][0] == 0) return; add(mp[w[pos]],1,0); dfs(G[pos][0]); add(mp[w[pos]],-1,0); add(mp[w[pos]],1,1); dfs(G[pos][1]); add(mp[w[pos]],-1,1);}int main(){#ifdef GLQ freopen("input.txt","r",stdin);// freopen("o4.txt","w",stdout);#endif // GLQ int t,n,m,q,i,j; scanf("%d",&t); while(t--) { mp.clear(); memset(a,0,sizeof(a)); scanf("%d",&n); for(i = 1; i <= n; i++) scanf("%d",&w[i]); scanf("%d",&m); memset(G,0,sizeof(G)); for(i = 0; i < m; i++) { int temp; scanf("%d",&temp); scanf("%d%d",&G[temp][0],&G[temp][1]); } memcpy(wei,w,sizeof(w)); sort(wei+1,wei+1+n); nct = unique(wei+1,wei+n+1)-wei-1; for(i = 1; i <= nct; i++) mp[wei[i]] = i; scanf("%d",&q); for(i = 1; i <= n; i++) v[i].clear(); for(i = 0; i < q; i++) { int p,x; scanf("%d%d",&p,&x); v[p].push_back(make_pair(i,x)); } dfs(1); for(i = 0; i < q; i++) if(ans[i][0] == -1) printf("0\n"); else printf("%d %d\n",ans[i][0],ans[i][1]); } return 0;}
0 0
- hdu 4605 Magic Ball Game(离线+树状数组)
- HDU 4605 Magic Ball Game 树状数组
- HDU 4605 Magic Ball Game 树状数组
- Magic Ball Game - HDU 4605 树状数组
- HDU 4605 Magic Ball Game 树状数组
- hdu 4605-Magic Ball Game(树状数组)
- hdu-4605 Magic Ball Game[离散化+回溯+树状数组]
- HDU 4605 Magic Ball Game(离线、BIT)
- HDU 4605 Magic Ball Game(可持续化线段树,树状数组,离散化)
- hdu-4605-Magic Ball Game-线段树+离线操作
- hdu4605 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
- HDU.4605 Magic Ball Game
- HDU 4605 Magic Ball Game 解题报告
- 1018. Public Bike Management (30)
- Object
- c#文件浏览器
- PostgreSQL实用SQL
- example: call cuda toolkit API from python, curand
- hdu 4605 Magic Ball Game(离线+树状数组)
- JAVA:相对路径显示图标
- 第三方框架 - @“失败不可怕”
- Object 2
- 图书管理系统1
- 字符串的压缩(待修订)
- android Adapter
- MD5加密java
- RSA算法原理(一)