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 ...
随机推荐
- POJ 3233 Matrix Power Series (矩阵+二分+二分)
题目地址:http://poj.org/problem?id=3233 题意:给你一个矩阵A,让你求A+A^2+……+A^k模p的矩阵值 题解:我们知道求A^n我们可以用二分-矩阵快速幂来求,而 当k ...
- CVPR读书笔记[5]:Gabor特征提取之Gabor核的实现
朱金华 jinhua1982@gmail.com 2014.08.09 本文參考http://blog.csdn.net/njzhujinhua/article/details/38460861 ...
- Laravel 4 Quick Tip: Custom Error Pages
App::error(function($exception, $code) { switch ($code) { case 403: return Response::view('errors.40 ...
- MySQL-视频跟随练习笔记
在表中添加某列 alter table tbl_user add email varchar(50); 在表中删除某列 alter table tbl_user drop email; 重命名某列 a ...
- ubuntu安装kvm流程
1. 查看CPU的虚拟化支持~ egrep 'svm|vmx' /proc/cpuinfo #查看是否有内容输出 2. 更新源~ sudo apt-get update 安装KVM及virt管理软件~ ...
- java03变量和基本数据类型
/** * * 失去一日甚易,欲得回已无途! * * 关键字:java中的关键字 就是指 已经被定义了的单词! * 我们就不能再拿关键字 作为我们的变量名! * 常用的关键字: * 基本数据类型: * ...
- 03-StreamReader和StreamWriter的案例
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...
- ado.net(1)
connection对象处于最顶层,是所有数据请求的关口 数据库连接过程 SqlConnection theConnection = new SqlConnection(); //创建一个connec ...
- CentOS 6.4搭建zabbix
系统环境:CentOS 6.4 64bit Zabbix版本:zabbix 2.2.3 前提条件:已安装好LNMP环境 一.服务端: 1. 下载zabbix安装包zabbix-2.2.3.tar.g ...
- oracle PL/SQL程序设计
declare 说明部分 (变量说明,光标申明,例外说明 ] begin 语句序列 (DML语句]… exception 例外处理语句 End; /