版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu 4605

题意:

  有一颗树,根节点为1,每一个节点要么有两个子节点,要么没有,每个节点都有一个权值wi 。然后,有一个球,附带值x 。

  球到达某个节点上,如果x==wi,那么球停在这个节点上 。当然,这个点是叶子节点也会停止 。

  如果x<wi,那么有1/2的概率走向左子树,有1/2的概率走向右子树 。

  如果x>wi,那么有1/8的概率走向左子树,有7/8的概率走向右子树 。

  问球经过v节点的概率 。(停在v节点也算)

解法:

  在线的话每一个节点建一棵根节点到该节点的线段树,离线的话就先把询问按DFS序排序,然后瞎搞搞就ok了 。。。

在线主席树

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#define ll long long using namespace std; const int N=; int Ls[N*],Rs[N*],cnt[N*][];
int root[N],tot; int e[N][];
int w[N],sort_w[N]; int n; inline int Hash(int x){
return upper_bound(sort_w+,sort_w+n+,x)-sort_w-;
} inline void init(){
tot=;
memset(e,-,sizeof(e));
} inline int bulidtree(int L,int R){
int k=tot++;
cnt[k][]=cnt[k][]=;
if (L==R) return k;
int mid=(L+R)>>;
Ls[k]=bulidtree(L,mid);
Rs[k]=bulidtree(mid+,R);
return k;
} inline void copy(int x,int y){
Ls[x]=Ls[y];
Rs[x]=Rs[y];
cnt[x][]=cnt[y][];
cnt[x][]=cnt[y][];
} // to 0 左子树 1 右子树
inline int update(int o,int p,int to,int L,int R){
int k=tot++;
copy(k,o);
cnt[k][to]++;
if (L==R) return k;
int mid=(L+R)>>;
if (p<=mid) Ls[k]=update(Ls[k],p,to,L,mid);
else Rs[k]=update(Rs[k],p,to,mid+,R);
return k;
} inline int query(int o,int x,int y,int to,int L,int R){
if (x>y) return ;
if (L==x && R==y) return cnt[o][to];
int mid=(L+R)>>;
if (y<=mid) return query(Ls[o],x,y,to,L,mid);
else if (x>mid) return query(Rs[o],x,y,to,mid+,R);
else return query(Ls[o],x,mid,to,L,mid)+query(Rs[o],mid+,y,to,mid+,R);
} inline void dfs(int u){
for (int i=;i<=;i++) if (~e[u][i]) {
int v=e[u][i];
root[v]=update(root[u],Hash(w[u]),i,,n);
dfs(v);
}
} int main(){
int t,m,q;
scanf("%d",&t);
while (t--){
init(); scanf("%d",&n);
for (int i=;i<=n;i++) {
scanf("%d",&w[i]);
sort_w[i]=w[i];
}
sort(sort_w+,sort_w+n+); scanf("%d",&m);
while (m--){
int u,a,b;
scanf("%d %d %d",&u, &a, &b);
e[u][]=a;
e[u][]=b;
} root[]=bulidtree(,n); dfs(); scanf("%d",&q);
while (q--){
int v,x;
scanf("%d %d",&v,&x);
int id=Hash(x);
if (x==sort_w[id]){
if (query(root[v],id,id,,,n) || query(root[v],id,id,,,n)){
puts("");
continue;
}
} int L_down=query(root[v],,id,,,n);
int L_up=query(root[v],id+,n,,,n);
int R_down=query(root[v],,id,,,n);
int R_up=query(root[v],id+,n,,,n); printf("%d %d\n",R_down,L_up+R_up+*L_down+*R_down);
}
} return ;
}

离线树状数组

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#define ll long long using namespace std; const int N=; int w[N],e[N][];
int sort_w[N];
int c[N][]; // 树状数组
int n,Q;
int pos[N];
int ans[N][]; struct QUERY{
int v,x,id;
int s;
bool operator < (const QUERY & t) const {
return s<t.s;
}
}q[N]; inline int Hash(int x){
return upper_bound(sort_w+,sort_w+n+,x)-sort_w-;
} inline void init(){
memset(c,,sizeof(c));
memset(e,,sizeof(e));
} inline int lowbit(int x){
return x&(-x);
} inline void add(int x,int d,int to){
while (x<=n){
c[x][to]+=d;
x+=lowbit(x);
}
} inline int sum(int x,int to){
int ret=;
while (x){
ret+=c[x][to];
x-=lowbit(x);
}
return ret;
} inline int query(int L,int R,int to){
return sum(R,to)-sum(L-,to);
} int cnt;
inline void dfs1(int u){
pos[u]=++cnt;
for (int i=;i<=;i++) if (e[u][i])
dfs1(e[u][i]);
} inline void dfs2(int u){
while (cnt<=Q && q[cnt].v==u){
int id=Hash(q[cnt].x);
if (sort_w[id]==q[cnt].x){
if (query(id,id,) || query(id,id,)){
ans[q[cnt].id][]=-;
cnt++;
continue;
}
} int L_down=query(,id,);
int L_up=query(id+,n,);
int R_down=query(,id,);
int R_up=query(id+,n,); ans[q[cnt].id][]=R_down;
ans[q[cnt].id][]=L_up+R_up+*L_down+*R_down;
cnt++;
} int id=Hash(w[u]);
for (int i=;i<=;i++) if (e[u][i]) {
add(id,,i);
dfs2(e[u][i]);
add(id,-,i);
}
} int main(){
int t,m;
scanf("%d",&t);
while (t--){
init(); scanf("%d",&n);
for (int i=;i<=n;i++) {
scanf("%d",&w[i]);
sort_w[i]=w[i];
}
sort(sort_w+,sort_w+n+); scanf("%d",&m);
for (int i=;i<=m;i++){
int u,a,b;
scanf("%d %d %d",&u, &a, &b);
e[u][]=a;
e[u][]=b;
} scanf("%d",&Q);
for (int i=;i<=Q;i++){
scanf("%d%d",&q[i].v,&q[i].x);
q[i].id=i;
} cnt=;
dfs1(); for (int i=;i<=Q;i++) q[i].s=pos[q[i].v];
sort(q+,q+Q+); cnt=;
dfs2(); for (int i=;i<=Q;i++){
if (~ans[i][]) printf("%d %d\n",ans[i][],ans[i][]);
else puts("");
}
} return ;
}

hdu 4605 Magic Ball Game (在线主席树/离线树状数组)的更多相关文章

  1. HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题意:给出一棵二叉树,每个结点孩子数目为0或者2. ...

  2. HDU 4605 Magic Ball Game(可持续化线段树,树状数组,离散化)

    Magic Ball Game Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  3. HDU 4605 Magic Ball Game (dfs+离线树状数组)

    题意:给你一颗有根树,它的孩子要么只有两个,要么没有,且每个点都有一个权值w. 接着给你一个权值为x的球,它从更节点开始向下掉,有三种情况 x=w[now]:停在此点 x<w[now]:当有孩子 ...

  4. HDU 4605 Magic Ball Game 树状数组

    题目大意很简单. 有一颗树(10^5结点),所有结点要么没有子结点,要么有两个子结点.然后每个结点都有一个重量值,根结点是1 然后有一个球,从结点1开始往子孙结点走. 每碰到一个结点,有三种情况 如果 ...

  5. hdu 4605 Magic Ball Game

    http://acm.hdu.edu.cn/showproblem.php?pid=4605 可以离线求解 把所以可能出现的 magic ball  放在一个数组里(去重),从小到大排列 先不考虑特殊 ...

  6. HDU 4605 Magic Ball Game 主席树

    题意: 给一棵\(n(1 \leq n \leq 10^5)\)个节点的二叉树,除叶子节点外,每个点都有左儿子和右儿子. 每个点上都有一个权值. 游戏规则是这样的:在根节点放一个权值为\(X\)的小球 ...

  7. HDU 4605 Magic Ball Game(离线算法)

    题目链接 思路就很难想+代码实现也很麻烦,知道算法后,已经写的很繁琐而且花了很长时间,200+,好久没写过这么长的代码了. #pragma comment(linker, "/STACK:1 ...

  8. HDU 4602 Magic Ball Game(离线处理,树状数组,dfs)

    Magic Ball Game Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  9. 【HDOJ】4605 Magic Ball Game

    思路1:树状数组+离线处理,对所有的w离散化处理,边dfs边使用树状数组更新左右w的情况.思路2:主席树,边bfs边建树.结点信息存储cnt,然后在线查询.树状数组. /* 4605 */ #incl ...

随机推荐

  1. java网络编程(二)可中断套接字

    参考资料:java核心技术 卷II 为中断套接字操作,可使用java.nio包提供的SocketChannel类.可以使用如下方式打开SocketChannel: SocketChannel chan ...

  2. Oracle中三种循环(For、While、Loop)案例

    1.ORACLE中的FOR循环用法(九九乘法表) declare i ; j ; begin .. loop ..i loop Dbms_Output.put(i||'*'||j||'='||i*j) ...

  3. appium手机操作

    1.按键操作 pressKeyCode(key, metastate) key为按键事件,metastate为辅助功能键 举例: pressKeyCode(AndroidKeyCode.HOME)   ...

  4. click()、bind()、live()和delegate()方法

    我之前使用click()比较多,又来因为网页内容需要前端生成用了live().有的时候使用click()和bind()分不清楚该怎么试用.查了很多资料.测试了很多次,自己明白了. 总结如下:代码注释很 ...

  5. 移动端开发-viewport

    1.viewport viewport 即设备 屏幕上显示网页的区域.因为移动设备屏幕比较小,为了能让移动设备能够显示更多内容,默认设置的viewport 并不是屏幕真是像素点的宽度,一般为980px ...

  6. MySQL一主两从

    服务器说明: MySQL-Master:192.168.1. MySQL-Slave1:192.168.1. MySQL-Slave2:192.168.1. 关闭防火墙,关闭selinux 统一采用源 ...

  7. BZOJ4951 Wf2017Money for Nothing(决策单调性)

    按时间排序,显然可能存在于答案中的公司价格应该单调递减.然后就可以大胆猜想感性证明其有决策单调性.具体地,设f(i,j)表示第i个消费公司和第j个生产公司搭配的获利,f(i,j)=(ti-tj)*(c ...

  8. 《Node入门》读书笔记——用Node.js开发一个小应用

    Android APP的开发告一段落,一个稳定的.实现了基本功能的APP已经交付用户使用了!我和老板交流了下,接下来准备转战Node.js了,而且一部分前端的功能也要做进去!哈哈哈~~~接下来要朝一个 ...

  9. 解题:POI 2015 Kinoman

    题面 发现每种电影只在两场之间产生贡献(只有$pos$的一场的就在$[pos,n]$产生贡献).那么我们针对每个位置$i$求出这场电影下一次出现的位置$nxt[i]$,然后每次更新一下,求整个区间的最 ...

  10. HDU4625 JZPTREE——第二类斯特林数

    复杂度大概O(nk) 一些尝试:1.对每个点推出1,2,3,,,到k次方的值.但是临项递推二项式展开也要考虑到具体每个点的dist 2.相邻k次方递推呢?递推还是不能避免k次方的展开 k次方比较讨厌, ...