HDU4605---Magic Ball Game(主席树 好题)
题意:一颗二叉树,任意节点要么有两个孩子要么没孩子。
然后有一个球,从结点1开始往子孙结点走。
每碰到一个结点,有三种情况
如果此球重量等于该结点重量,球就停下了
如果此球重量小于该结点重量,则分别往左右儿子走的可能都是1/2
如果此球重量大于该结点重量,则走向左儿子的概率是1/8,右儿子的概率是7/8
然后若干个询问(10^5次),问一个重量为x的球经过结点v的概率
观察路径,可以发现路径可以分成两种,向左走的路径和向右走的路径,分成这两种是因为各自的计算公式,在向左走的路径中,设大于x的点权有a个,小于x的点权有b个,同理定义c d,我们只需要求出a b c d 就可以了。
做法:
貌似很多做法,,我是用主席树多的,对于节点V,建立根节点1到V的前缀线段树,(此过程bfs实现)利用主席树的性质。
然后主席树里面存两个信息,一个是向左走的一个是向右走的。(此题一些细节,二分的时候不注意的话就会一直wa)
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std; const int maxn = 1e5+;
struct Edge
{
int to,next,kind;
} e[maxn<<];
int head[maxn],edge_idx;
void add_edge(int x,int y,int kind)
{
e[edge_idx].to = y;
e[edge_idx].next = head[x];
e[edge_idx].kind = kind;
head[x] = edge_idx++;
}
//----------------------------------
int lcnt[maxn*],rcnt[maxn*],lson[maxn*],rson[maxn*];
int tree[maxn<<],tot,tree_max;
int build (int l,int r)
{
int root = tot++;
lcnt[root] = rcnt[root] = ;
if (l != r)
{
int mid = (l + r) >> ;
lson[root] = build(l,mid);
rson[root] = build(mid+,r);
}
return root;
}
int update (int root,int pos,int lval,int rval)
{
int newroot = tot++;
int tmp = newroot;
int l = ,r = tree_max;
lcnt[newroot] = lcnt[root] + lval;
rcnt[newroot] = rcnt[root] + rval;
while (l < r)
{
int mid = (l + r) >> ;
if (pos <= mid)
{
r = mid;
rson[newroot] = rson[root];
root = lson[root];
lson[newroot] = tot++;
newroot = lson[newroot];
}
else
{
l = mid + ;
lson[newroot] =lson[root];
root = rson[root];
rson[newroot] = tot++;
newroot = rson[newroot];
}
lcnt[newroot] = lcnt[root] + lval;
rcnt[newroot] = rcnt[root] + rval;
}
return tmp;
}
int query(int root,int l,int r,int ua,int ub,int kind)
{
if (ub < ua)
return ;
if (ua <= l && ub >= r)
{
if (kind)
return rcnt[root];
else
return lcnt[root];
}
int mid = (l + r) >> ;
int t1 = , t2 = ;
if (ua <= mid)
t1 = query(lson[root],l,mid,ua,ub,kind);
if (ub > mid)
t2 = query(rson[root],mid+,r,ua,ub,kind);
return t1 + t2;
} int W[maxn],vec[maxn],idx;
int hash_(int x)
{
return lower_bound(vec,vec+idx,x) - vec + ;
}
void init()
{
memset(head,-,sizeof(head));
idx = tot = ;
edge_idx = ;
}
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int T;
scanf ("%d",&T);
while (T--)
{
init();
int n,q,m;
scanf ("%d",&n);
for (int i = ; i < n ; i++)
{
scanf ("%d",W+i+);
vec[idx++] = W[i+];
}
sort(vec,vec+idx);
idx = unique(vec,vec+idx) - vec;
scanf ("%d",&m);
for (int i = ; i < m; i++)
{
int x,lf,rg;
scanf ("%d%d%d",&x,&lf,&rg);
add_edge(x,lf,);
add_edge(x,rg,);
}
tree_max = n;
tree[] = build(,n); queue<int>Q;
while (!Q.empty())
Q.pop();
Q.push();
while (!Q.empty())
{
int x = Q.front();
Q.pop();
for (int i = head[x]; ~i; i = e[i].next)
{
int v,k;
v = e[i].to, k = e[i].kind;
tree[v] = update(tree[x],hash_(W[x]),k == , k == );
Q.push(v);
}
}
scanf ("%d",&q);
for (int i = ; i < q; i++)
{
int x,v;
scanf ("%d%d",&v,&x);
if (v == )
{
printf("0 0\n");
continue;
}
int tmp = x; //
x = hash_(x); // 二分得到的值可能原数组并不存在
int ua = x-, ub = x; //理论上要查询x+1,但是如果tmp在原数组中不存在,那么就不用+1了
int flag = ;
flag = query(tree[v],,n,x,x,) + query(tree[v],,n,x,x,);
if (vec[x-] == tmp)
{
if (flag)
{
printf("0\n");
continue;
}
ub++;
}
int lf_small = query(tree[v], , n, , ua, );
int lf_big = query(tree[v], , n, ub, n, );
int rg_small = query(tree[v], , n, , ua, );
int rg_big = query(tree[v], , n, ub, n, );
int ans1 = , ans2 = ;
ans1 += rg_small;
ans2 += *(rg_small+lf_small) + rg_big + lf_big;
printf("%d %d\n",ans1,ans2);
}
}
return ;
}
HDU4605---Magic Ball Game(主席树 好题)的更多相关文章
- HDU 4605 Magic Ball Game 主席树
题意: 给一棵\(n(1 \leq n \leq 10^5)\)个节点的二叉树,除叶子节点外,每个点都有左儿子和右儿子. 每个点上都有一个权值. 游戏规则是这样的:在根节点放一个权值为\(X\)的小球 ...
- 【POJ 2104】 K-th Number 主席树模板题
达神主席树讲解传送门:http://blog.csdn.net/dad3zz/article/details/50638026 2016-02-23:真的是模板题诶,主席树模板水过.今天新校网不好,没 ...
- BZOJ4408: [Fjoi 2016]神秘数【主席树好题】
Description 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13}, 1 = 1 2 = 1+1 3 = 1+1+1 4 = 4 5 = ...
- poj2104 主席树模板题
题意 给出n个数字组成的数字序列,有m组询问.每次询问包含三个数字l,r,k.对于每个询问输出序列区间[l,r]中第k大的数字. 分析 这是主席树的模板题,套板子就可以 #include <cs ...
- POJ 2104 求序列里第K大 主席树裸题
给定一个n的序列,有m个询问 每次询问求l-r 里面第k大的数字是什么 只有询问,没有修改 可以用归并树和划分树(我都没学过..囧) 我是专门冲着弄主席树来的 对主席树的建树方式有点了解了,不过这题为 ...
- 【BZOJ 1901】【Zju 2112】 Dynamic Rankings 动态K值 树状数组套主席树模板题
达神题解传送门:http://blog.csdn.net/dad3zz/article/details/50638360 说一下我对这个模板的理解: 看到这个方法很容易不知所措,因为动态K值需要套树状 ...
- 主席树:POJ2104 K-th Number (主席树模板题)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 44952 Accepted: 14951 Ca ...
- SPOJ MKTHNUM & POJ 2104 - K-th Number - [主席树模板题]
题目链接:http://poj.org/problem?id=2104 Description You are working for Macrohard company in data struct ...
- POJ 2104 K-th Number(主席树模板题)
http://poj.org/problem?id=2104 题意:求区间$[l,r]$的第k小. 思路:主席树不好理解啊,简单叙述一下吧. 主席树就是由多棵线段树组成的,对于数组$a[1,2...n ...
随机推荐
- jQuery实现密保互斥问题
密保互斥问题: 密保通常都会有n个问题,让用户选择其中2.3个,而且都不会让用户选择重复的问题.这就要求密保互斥. 效果如下: 下面我用了jquery实现密保互斥,用于解决密保,投票等类似互斥问题,可 ...
- LVS+Keepalived实现MySQL从库读操作负载均衡
http://www.osyunwei.com/archives/7464.html (学习运维知识好站) 说明: 操作系统:CentOS 5.X 64位 MySQL主服务器:192.168.21.1 ...
- hdu3368之DFS
Reversi Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Su ...
- [转] GDB attach
转:http://blog.csdn.net/wangeen/article/details/14230171 attach是GDB一种重要的debug模式,在MPI程序debug中发挥重要的作用. ...
- 九宫重拍(bfs + 康拓展开)
问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成第二个图所示的局面. 我们把第一个图的局面记为:12 ...
- Vitamio 多媒体框架 介绍
功能 Vitamio 是一款 Android 与 iOS 平台上的全能多媒体开发框架,全面支持硬件解码与 GPU 渲染.Vitamio 凭借其简洁易用的 API 接口赢得了全球众多开发者的青睐.到目前 ...
- javascript:void(0)知多少
在做页面时,如果想做一个链接点击后不做任何事情,或者响应点击而完成其他事情,可以设置其属性 href = "#",但是,这样会有一个问题,就是当页面有滚动条时,点击后会返回到页面顶 ...
- knockout --- foreach -- 前端必备
很久很久没写博客了,丫的,节操掉一地了,颓废了,惭愧. 很久很久没有弄 knouckout.js 了,今天重新操作,蛋疼啊,忘记得差不多了,于是只好硬着头皮再去看官网,于是,feel慢慢回来了. 本来 ...
- 百度背景画面切换效果,js做
<!DOCTYPE html><html><head> <title>baidu</title> <meta charset=&quo ...
- sql数据库之间数据的转录
private void Form1_Load(object sender, EventArgs e) { BindDataBase(combDataBaseNew, , ""); ...