hdu4605Magic Ball Game 树状数组

Posted llguanli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu4605Magic Ball Game 树状数组相关的知识,希望对你有一定的参考价值。

//给一棵树。树的每个节点的子节点个数是0或2
//对于每个节点都有一个权值w[i]
//一个权值为x的球在每个节点的情况有
//x=w[i] 这个球在该点不向下掉
//x<w[i] 这个球往左节点和右节点掉的概率各为1/2
//x>w[i] 这个球往左节点掉的概率为1/8 , 往右掉的概率为7/8
//问对于每个权值为x其掉到节点为v的概率


//对于一颗树从一点到还有一点的路径是确定的,仅仅须要记录这条路径中
//往左走的路径中大于x的节点个数 l_grt,小于x的节点个数l_less
//往右走中大于x的节点个数 r_grt , 小于x的节点个数r_less
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std ;
const int maxn = 1e6+10 ;
int map[maxn][2] ;
vector<int> vec[maxn] ;
int x[maxn] , y[maxn] ;
int root[maxn] ;
int w_x[maxn] ;
int ?w[maxn] ;
int a[maxn] ;int len ;
int tree[2][maxn] ;
void update(int x , int flag , int dx)
{
? ? while(x < maxn)
? ? {
? ? ? ? tree[flag][x] += dx ;
? ? ? ? x += x&(-x) ;
? ? }
}
int getsum(int x ,int flag)
{
? ? int sum = 0 ;
? ? while(x)
? ? {
? ? ? ? sum += tree[flag][x] ;
? ? ? ? x -= x&(-x) ;
? ? }
? ? return sum ;
}
void dfs(int u)
{
? ? //cout<<u<<endl;
? ? for(int i = 0;i < vec[u].size() ;i++)
? ? {
? ? ? ? int id = vec[u][i] ;
? ? ? ? int pos = lower_bound(a, a + len - 1, w_x[id]) - a + 1;
? ? ? ? int l_less = getsum(pos - 1 , 0) ;
? ? ? ? int r_less = getsum(pos - 1, 1) ;
? ? ? ? int l_all = getsum(len , 0) ;
? ? ? ? int r_all = getsum(len , 1) ;
? ? ? ? int l_grt = l_all - getsum(pos , 0) ;
? ? ? ? int r_grt = r_all - getsum(pos , 1) ;
? ? ? ? if(l_less + r_less + l_grt + r_grt != l_all + r_all)
? ? ? ? {
? ? ? ? ? ? x[id] = y[id] = -1 ;
? ? ? ? ? ? continue ;
? ? ? ? }
? ? ? ? x[id] = r_less ;
? ? ? ? y[id] = l_grt + r_grt + (l_less + r_less)*3 ;
? ? }
? ? for(int i = 0;i < 2;i++)
? ? {
? ? ? ? if(!map[u][i])continue ;
? ? ? ? int v = map[u][i] ;
? ? ? ? int pos = lower_bound(a , a + len - 1 , w[u]) - a + 1 ;
? ? ? ? update(pos , i , 1) ;
? ? ? ? dfs(v) ;
? ? ? ? update(pos , i , -1) ;
? ? }
}
int main()
{
? ? //freopen("in.txt" ,"r" , stdin) ;
? ? int T ;
? ? int N ;int M , Q ;
? ? scanf("%d" , &T) ;
? ? while(T--)
? ? {
? ? ? ? scanf("%d" , &N) ;
? ? ? ? len = 0 ;
? ? ? ? for(int i = 1;i <= N;i++)
? ? ? ? {
? ? ? ? ? ? scanf("%d" , &w[i]) ;
? ? ? ? ? ? a[len++] = w[i] ;
? ? ? ? }
? ? ? ? sort(a , a + N) ;
? ? ? ? len = unique(a , a + len) - a ;
? ? ? ? scanf("%d" ,&M) ;
? ? ? ? memset(map , 0 , sizeof(map)) ;
? ? ? ? memset(root , 0 , sizeof(root)) ;
? ? ? ? while(M--)
? ? ? ? {
? ? ? ? ? ? int u , l , r ;
? ? ? ? ? ? scanf("%d%d%d" , &u , &l , &r) ;
? ? ? ? ? ? map[u][0] = l ; map[u][1] = r ;
? ? ? ? ? ? root[l] = root[r] = 1;
? ? ? ? }
? ? ? ? scanf("%d" , &Q) ;
? ? ? ? for(int i = 1;i <= Q ;i++)
? ? ? ? {
? ? ? ? ? ? int v ;
? ? ? ? ? ? scanf("%d%d" , &v , &w_x[i]) ;
? ? ? ? ? ? vec[v].push_back(i) ;
? ? ? ? }
? ? ? ? int pos ;
? ? ? ? for(int i = 1;i <= N;i++)
? ? ? ? if(!root[i]){pos = i ;break;}
? ? ? ? dfs(pos) ;
? ? ? ? for(int i = 1;i <= Q;i++)
? ? ? ? {
? ? ? ? ? ? if(x[i]==-1)puts("0") ;
? ? ? ? ? ? else printf("%d %d\n" ?, x[i] , y[i]) ;
? ? ? ? }
? ? }
}

































































以上是关于hdu4605Magic Ball Game 树状数组的主要内容,如果未能解决你的问题,请参考以下文章

hdu4605Magic Ball Game 树状数组

HDOJ4605 Magic Ball Game

hdu4605

Shell Game-枚举,找规律

HDU-4811-Ball(思维)

hdu-4811 Ball