HDU 4605 Magic Ball Game(离线、BIT)
2016-02-28 00:44
399 查看
题意:
根为1的N≤105个节点的无向树,所有结点有2个儿子或者没有儿子
每个节点的重量wi≤109,然后有一个球,从根开始往儿子结点走
每碰到一个节点,有三种情况:
如果此球重量等于该节点重量或者没有儿子节点了,球就停下了
如果此球重量小于该节点重量,则分别往左右儿子走的可能都是1/2
如果此球重量大于该节点重量,则走向左儿子的概率是1/8,右儿子的概率是7/8
Q≤105询问,问一个重量为x的球经过节点v的概率,表示成7x/2y,输出x,y
分析:
首先树上2点之间的路径是唯一的,所以离线询问按照dfs序来回答询问
离散化之后用2颗BIT来记录左路径和右路径上经过的点的重量
ans=12leftLarge∗18leftSmall∗12rightLarge∗78rightSmall
即x=rightSmall,y=leftLarge+rightLarge+3∗(leftSmall+rightSmall)
递归之前添加,别忘记回溯就好
时间复杂度为O((n+q)logn)
代码:
根为1的N≤105个节点的无向树,所有结点有2个儿子或者没有儿子
每个节点的重量wi≤109,然后有一个球,从根开始往儿子结点走
每碰到一个节点,有三种情况:
如果此球重量等于该节点重量或者没有儿子节点了,球就停下了
如果此球重量小于该节点重量,则分别往左右儿子走的可能都是1/2
如果此球重量大于该节点重量,则走向左儿子的概率是1/8,右儿子的概率是7/8
Q≤105询问,问一个重量为x的球经过节点v的概率,表示成7x/2y,输出x,y
分析:
首先树上2点之间的路径是唯一的,所以离线询问按照dfs序来回答询问
离散化之后用2颗BIT来记录左路径和右路径上经过的点的重量
ans=12leftLarge∗18leftSmall∗12rightLarge∗78rightSmall
即x=rightSmall,y=leftLarge+rightLarge+3∗(leftSmall+rightSmall)
递归之前添加,别忘记回溯就好
时间复杂度为O((n+q)logn)
代码:
// // Created by TaoSama on 2016-02-26 // Copyright (c) 2016 TaoSama. All rights reserved. // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; #define pr(x) cout << #x << " = " << x << " " #define prln(x) cout << #x << " = " << x << endl const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7; int n, m, q; int son [2], w ; vector<pair<int, int> > Q ; struct BIT { int n, b[N << 1]; void init(int _n) { n = _n; memset(b, 0, sizeof b); } void add(int i, int v) { for(; i <= n; i += i & -i) b[i] += v; } int sum(int i) { int ret = 0; for(; i; i -= i & -i) ret += b[i]; return ret; } int getAll() { return sum(n); } } bit[2]; //0 for left, 1 for right vector<int> xs; pair<int, int> ans ; //ans = 1/2 ^ leftLarge * 1/8 ^ leftSmall; // * 1/2 ^ rightLarge * 7/8 ^ rightSmall; void dfs(int u) { int leftAll = bit[0].getAll(), rightAll = bit[1].getAll(); for(auto p : Q[u]) { //answer queries int x = p.first, id = p.second; x = lower_bound(xs.begin(), xs.end(), x) - xs.begin() + 1; int leftSmall = bit[0].sum(x - 1), leftLarge = leftAll - bit[0].sum(x); int rightSmall = bit[1].sum(x - 1), rightLarge = rightAll - bit[1].sum(x); //if equal ones exist if(leftAll + rightAll - leftSmall - leftLarge - rightSmall - rightLarge) { ans[id] = { -1, -1}; continue; } ans[id].first = rightSmall; ans[id].second = leftLarge + rightLarge + 3 * (leftSmall + rightSmall); } w[u] = lower_bound(xs.begin(), xs.end(), w[u]) - xs.begin() + 1; for(int i = 0; i < 2; ++i) { int v = son[u][i]; if(!v) continue; bit[i].add(w[u], 1); //add before go down dfs(v); bit[i].add(w[u], -1); //back } } int main() { #ifdef LOCAL freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin); // freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); int t; scanf("%d", &t); while(t--) { scanf("%d", &n); xs.clear(); for(int i = 1; i <= n; ++i) { scanf("%d", w + i); xs.push_back(w[i]); } scanf("%d", &m); memset(son, 0, sizeof son); while(m--) { int u; scanf("%d", &u); for(int i = 0; i < 2; ++i) scanf("%d", son[u] + i); } scanf("%d", &q); for(int i = 1; i <= n; ++i) Q[i].clear(); for(int i = 1; i <= q; ++i) { int v, x; scanf("%d%d", &v, &x); xs.push_back(x); Q[v].push_back({x, i}); } sort(xs.begin(), xs.end()); xs.resize(unique(xs.begin(), xs.end()) - xs.begin()); for(int i = 0; i < 2; ++i) bit[i].init(xs.size()); dfs(1); for(int i = 1; i <= q; ++i) if(~ans[i].first) printf("%d %d\n", ans[i].first, ans[i].second); else puts("0"); } return 0; }
相关文章推荐
- 一个有趣的SQL命题 用一条语句切换BIT型的真假值
- Java数据结构及算法实例:快速计算二进制数中1的个数(Fast Bit Counting)
- bit 10_18
- java 基本数据所占内存大小
- Single Number II
- Bit与Byte的区别
- Number of 1 Bits
- Bit manipulation
- HDU 1166 - 敌兵布阵 - Segment Tree
- poj 3109 扫描线+bit
- poj 2155 二维树状数组/区间更新单点查询
- 位操作 示例程序
- Basic Binary Indexed Tree
- hdu 1556 Color the ball 树状数组
- hdu 2852 KiKi's K-Number 树状数组
- hdu1541 star 树状数组
- hdu 2838 Cow Sorting 树状数组
- [Leetcode]#136 Single Number
- leetcode[231]:Power of Two
- leetcode[136]:Single Number