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 ...
随机推荐
- Android dp和px之间转换 及 获取坐标
dp.px.sp转换 public class DensityUtil { /** * 将px值转换为dip或dp值,保证尺寸大小不变 * * @param pxValue * @param scal ...
- TinyXml 快速入门(三)
在<TinyXml 快速入门(二)>介绍使用tinyxml库获取xml文件声明,查询指定节点.删除指定节点的做法.在本文中继续介绍修改指定节点和增加节点的做法. 修改节点其实和查询指定节点 ...
- api接口
目录(?)[-] 接口特点汇总 PHP Token令牌 先说第一个tokenapi_token 服务端接口校验PHP实现流程如下 再说第二个tokenuser_token 接口用例如下 接口特点汇总: ...
- 属性动画 LayoutTransition AnimatorInflater Keyframe 新特性
LayoutTransition设置动画 使用LayoutTransition可为布局的容器设置动画,当容器中的视图层次发生变化时产生相应的过渡的动画效果 过渡的类型一共有四种: LayoutTran ...
- ASP.NET-FineUI开发实践-9
用了FineUI有一段时间了,还是分享下我咋改的吧,没想的那么难,我也是从小白来的. 基础是要懂JQ和EXTJS,主要是要懂JQ和EXTJS能干啥,这里有两个网站 http://www.w3schoo ...
- javascript高级特性(面向对象)
javascript高级特性(面向对象): * 面向对象: * 面向对象和面向过程的区别: * 面向对象:人就是对象,年龄\性别就是属性,出生\上学\结婚就是方法. * 面向过程:人出生.上学.工作. ...
- mongodb创建副本集命令
mongodb创建副本集命令 ./mongod --replSet spock --dbpath ../data --smallfiles > config ={... "_id&qu ...
- java 自定义注解以及获得注解的值
1.自定义注解 import java.lang.annotation.*; @Documented @Target(ElementType.FIELD) @Inherited @Retention( ...
- 1.Tomcat配置
1.启动 解压缩安装包后,点击startup.bat,保持控制台窗口开启 浏览器中输入http://localhost:8080 后看到启动界面则表示启动成功 点击shutdown.bat则关闭Tom ...
- Java中的内部类、匿名类的使用
代码(test.java): interface ie{ public void print(); } class outer{} public class test{ public class in ...