hdu 4605 树状数组 ****
题目大意很简单。
有一颗树(10^5结点),所有结点要么没有子结点,要么有两个子结点。然后每个结点都有一个重量值,根结点是1
然后有一个球,从结点1开始往子孙结点走。
每碰到一个结点,有三种情况
如果此球重量等于该结点重量,球就停下了
如果此球重量小于该结点重量,则分别往左右儿子走的可能都是1/2
如果此球重量大于该结点重量,则走向左儿子的概率是1/8,右儿子的概率是7/8
然后若干个询问(10^5次),问一个重量为x的球经过结点v的概率
仔细想一下,一个球走到某个结点,路径已经是固定的了,但是暴力肯定会超时,那么观察路径,可以发现路径可以分成两种,向左走的路径和向右走的路
径,分成这两种的原因也是因为各自的计算公式,在向左走的路径中,设大于x的点权有a个,小于x的点权有b个,那么向左走的路径概率就是p1=
(1/2)^a * (1/8) ^b, 同理向右的路径中概率
p2 = (1/2)^c * (7/8) ^d,最后二者相乘即是答案。
p1*p2则分母的指数就是d,分子的指数即为d/(a+c+3*b+3*d)
需要注意的是,如果从1到该点的路径中有一个点的重量等于x,那么这个点是永远被达不到的。
用树状数组维护指数即可
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
const int MAXN=;
int next[MAXN][];
int n;
int root;
int w[MAXN];
struct QQ
{
int v;
int X;
int ans1,ans2;
}Query[MAXN];
vector<int>vec[MAXN];
bool used[MAXN];
int a[MAXN];
map<int,int>mp; int c1[MAXN];
int c2[MAXN];
int t;
int lowbit(int x)
{
return x&(-x);
}
void add1(int i,int val)
{
while(i <= t)
{
c1[i] += val;
i += lowbit(i);
}
}
int sum1(int i)
{
int s = ;
while(i > )
{
s += c1[i];
i -= lowbit(i);
}
return s;
}
void add2(int i,int val)
{
while(i <= t)
{
c2[i] += val;
i += lowbit(i);
}
}
int sum2(int i)
{
int s = ;
while(i > )
{
s += c2[i];
i -= lowbit(i);
}
return s;
} void dfs(int u)
{
int sz = vec[u].size();
for(int i = ;i < sz;i++) //对于每个点上的询问
{
int id = vec[u][i];
int X = mp[Query[id].X];
if(sum1(X)-sum1(X-)!= || sum2(X)-sum2(X-)!=)
{
Query[id].ans1 = Query[id].ans2 = -;
}
else
{
Query[id].ans1 = Query[id].ans2 = ;
Query[id].ans2 += *sum1(X-)+sum1(t)-sum1(X);
Query[id].ans1 += sum2(X-);
Query[id].ans2 += *sum2(X-)+sum2(t)-sum2(X);
}
}
if(next[u][]== && next[u][]==)return;
add1(mp[w[u]],); //保证是有序的
dfs(next[u][]); //左走
add1(mp[w[u]],-); //恢复
add2(mp[w[u]],); //右走
dfs(next[u][]);
add2(mp[w[u]],-); //回溯法
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
int m;
int u,x,y;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i = ;i <= n;i++)
{
used[i] = false;
next[i][] = next[i][] = ;
vec[i].clear();
}
t = ;
for(int i = ;i <= n;i++)
{
scanf("%d",&w[i]);
a[t++] = w[i];
}
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d",&u,&x,&y);
used[x] = true;
used[y] = true;
next[u][] = x;
next[u][] = y;
}
scanf("%d",&m);
for(int i = ;i < m;i++)
{
scanf("%d%d",&u,&x);
Query[i].v = u;
Query[i].X = x;
a[t++] = x;
vec[u].push_back(i);
}
for(int i = ;i <= n;i++)
if(!used[i])
{
root = i;
break;
}
sort(a,a+t);
t = unique(a,a+t)-a;
mp.clear();
for(int i = ;i < t;i++)
mp[a[i]]=i+;
memset(c1,,sizeof(c1));
memset(c2,,sizeof(c2));
dfs(root);
for(int i = ;i < m;i++)
{
if(Query[i].ans1 == -)
printf("0\n");
else printf("%d %d\n",Query[i].ans1,Query[i].ans2);
}
}
return ;
}
hdu 4605 树状数组 ****的更多相关文章
- hdu 4638 树状数组 区间内连续区间的个数(尽可能长)
Group Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
- hdu 4777 树状数组+合数分解
Rabbit Kingdom Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- HDU 2852 (树状数组+无序第K小)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2852 题目大意:操作①:往盒子里放一个数.操作②:从盒子里扔掉一个数.操作③:查询盒子里大于a的第K小 ...
- HDU 4911 (树状数组+逆序数)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4911 题目大意:最多可以交换K次,就最小逆序对数 解题思路: 逆序数定理,当逆序对数大于0时,若ak ...
- hdu 5792(树状数组,容斥) World is Exploding
hdu 5792 要找的无非就是一个上升的仅有两个的序列和一个下降的仅有两个的序列,按照容斥的思想,肯定就是所有的上升的乘以所有的下降的,然后再减去重复的情况. 先用树状数组求出lx[i](在第 i ...
- HDU 1934 树状数组 也可以用线段树
http://acm.hdu.edu.cn/showproblem.php?pid=1394 或者是我自己挂的专题http://acm.hust.edu.cn/vjudge/contest/view. ...
- 2018 CCPC网络赛 1010 hdu 6447 ( 树状数组优化dp)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6447 思路:很容易推得dp转移公式:dp[i][j] = max(dp[i][j-1],dp[i-1][j ...
- 【模板】HDU 1541 树状数组
http://acm.hdu.edu.cn/showproblem.php?pid=1541 题意:给你一堆点,每个点右一个level,为其右下方所有点的数量之和,求各个level包含的点数. 题解: ...
- hdu 5147 树状数组
题意:求满足a<b<c<d,A[a]<A[b],A[c]<A[d]的所有四元组(a,b,c,d)的个数 看到逆序对顺序对之类的问题一开始想到了曾经用归并排序求逆序对,结果 ...
随机推荐
- C语言复习---选择法排序
选择排序也是一种简单直观的排序算法 它的工作原理很容易理解:初始时在序列中找到最小(大)元素,放到序列的起始位置作为已排序序列:然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾. ...
- 支付宝APP支付,提示代码 ALIN10070
ALIN10070 此代码时ALI64代码拆分后的细分代码: 代表签名验证失败等相关问题: 如果近期修改过或者续签 过签约协议,也需要更新公私钥.
- MySQL和Sql Server的sql语句区别
1.自增长列的插入:SQLServer中可以不为自动增长列插入值,MySQL中需要为自动增长列插入值. 2.获取当前时间函数:SQLServer写法:getdate()MySQL写法:now() 3. ...
- 论文中“but”与“however”的区别
- [整理]IE11中的WebGL探秘:渲染速度超Chrome
http://www.csdn.net/article/2013-12-19/2817854-IE11-WebGL-and-more 摘要:IE11开始支持WebGL,并且效果非常好,IE11的Web ...
- 从零开始编写自己的JavaScript框架(二)
2. 数据绑定 2.1 数据绑定的原理 数据绑定是一种很便捷的特性,一些RIA框架带有双向绑定功能,比如Flex和Silverlight,当某个数据发生变更时,所绑定的界面元素也发生变更,当界面元素的 ...
- python技巧 使用值来排序一个字典
In [8]: a={'x':11,'y':22,'c':4} In [9]: import operator In [10]: sorted(a.items(),key=operator.itemg ...
- JS种this的四种用法
记住以下四点: 1.没调用对象就指向全局对象 2.有对象就指向调用对象 3.用new构造就指向新对象 4.通过 apply 或 call 或 bind 来改变 this 的所指. 1.测试一:没调用对 ...
- Servlet笔记11--补充
Servlet线程安全问题: 代码示例: package com.bjpowernode.javaweb.servlet; import java.io.IOException; import jav ...
- Debian安装Nvidia最简单方法
电脑配置: Dell本本 i7+gtx1050+8g 安装bumblebee: sudo apt install bumblebee-nvidia primus 以上会自动安装nvidia驱动. bu ...