2013 多校第一场 hdu 4605 Magic Ball Game

来源:互联网 发布:怎么出售淘宝店铺 编辑:程序博客网 时间:2024/05/17 04:27

hdu 4605

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4605

题目大意:给你一棵二叉树,每个节点有一个w值,现在有一颗小球,值为x,从根节点往下掉,如果w==x,那么它就会停止;如果w>x,那么它往左、右儿子的概率都是1、2;如果w<x,那么它往左儿子的概率是1/8,右儿子是7/8。现在给你q个询问,问你值为x的球道达节点u的概率为多少。

思路:比赛的时候,我们都是跟着榜走的,都卡在那道Deque上了,根本没有看这题。昨天晚上自己看了一下,其实也没有什么正确的解题思路,暴力谁都会,但是肯定超时,要不然也不会比赛时没几个队伍去做这题了。然后,当然就看题解了喽,看题解先开始就是有一个地方一直不明白,它所说的树状数组(线段树)到底维护的是什么,它的区间又是什么东西。想来想去一直没想明白,去网上看别人的博客,东看西看又找了个同学去问,感觉也还是这几个地方不懂(当然不是他们讲的不好,而是我有个地方卡壳了,对线段树这个工具应用还不熟啊),后来,自己按照他们讲的方向去想了想,终于顿悟了。它不是每次询问都输出,而是先把所有的询问都存起来,遍历的时候一次性弄完,再输出,这个不是重点,关键还是在我上面所说的树状数组那里,对于树状数组来说,每个叶子节点A[ i ]存的是当前dfs 走过的路径上 w为 i 的结点个数,这样dfs下来的时候,每次都做update操作(递归时A[ w ]+1,回溯时再减掉),当当前节点被mark时,就询问。关于x、y的计算方法是这样的:设a为从根节点到当前节点左路径中小于x的节点数,b为从根节点到当前节点左路径中大于x的节点数,c为右路径中小于的,d为右路径中大于的,则 x = c,y = b+d+3*(a +c),这个自己画个图想想,列列式子就明白了。由于dfs到某个节点,对应的树状数组里存的就是这条路径对应的个数,询问的复杂度是O(logn)。多以整个过程在一遍dfs过后就完成了。由于分左、右路径,所以我就开了两个树状数组,一个表示左,一个表示右,那些开一个的其实也一样,都要分左、右的。

话说,这道题之前我只会线段树,树状数组不会,虽然说是一直都想学来着。。 = = ,因为这道题,网上大家写的都是树状数组,我也想看看树状数组到底是什么东西,就去学了。结果发现,这东西果然简单,学学就是5分钟的事情,然后再顺便A道题目。。 它能实现一些简单的求和和更新操作,虽然适用范围比线段树小,但是人家编程复杂度小啊,敲起来快,简单,空间也省。因为这道题只需要求和和单点更新,果断是树状数组啊!

今天早上来了,果断把它A了,可是我这个代码我发现一个神奇的问题,如果我在dfs中处理mark节点时如果sum(x),sum(x-1)这些值先算好保存下来(免得重复算么)再算要求的值,就是RE(爆栈),而直接当场就算,就是AC的。。 神奇啊,不解。。 = = 

代码如下:

#include<cstdio>#include<cstring>#include<map>#include<vector>#include<algorithm>using namespace std;#define MP make_pairconst int MAXN = 111111 ;struct Node{    int w,lson,rson;} node[MAXN];int mark[MAXN];vector < pair <int,int> > ques[MAXN];int ans[MAXN][2];int tot;int sum_l[MAXN],sum_r[MAXN];map <int,int> my_map;int lowbit(int x){    return x&(-x);}void update_left(int pos,int x){    while(pos<=tot)    {        sum_l[pos]+=x;        pos += lowbit(pos);    }}void update_right(int pos,int x){    while(pos<=tot)    {        sum_r[pos]+=x;        pos += lowbit(pos);    }}int sum_left(int pos){    int s=0;    while(pos>=1)    {        s += sum_l[pos];        pos -= lowbit(pos);    }    return s;}int sum_right(int pos){    int s=0;    while(pos>=1)    {        s += sum_r[pos];        pos -= lowbit(pos);    }    return s;}void dfs(int root){    if(root==-1) return ;    if(mark[root])    {        for(int i = 0;i<ques[root].size();i++)        {            int x  = my_map[ques[root][i].first];            int id = ques[root][i].second;            if(sum_left(x)-sum_left(x-1)>0||sum_right(x)-sum_right(x-1)>0) ans[id][0] = -1;            else            {                ans[id][0] = sum_right(x-1);                ans[id][1] = sum_left(tot)-sum_left(x)+sum_right(tot)-sum_right(x)+3*(sum_left(x-1)+sum_right(x-1));            }        }    }    update_left(my_map[node[root].w],1);    dfs(node[root].lson);    update_left(my_map[node[root].w],-1);    update_right(my_map[node[root].w],1);    dfs(node[root].rson);    update_right(my_map[node[root].w],-1);}void init(){    memset(sum_l,0,sizeof(sum_l));    memset(sum_r,0,sizeof(sum_r));}int hash[MAXN];int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        for(int i=1;i<=n;i++)        {            scanf("%d",&node[i].w);            hash[i] = node[i].w;        }        int m;        scanf("%d",&m);        int a,b,c;        for(int i =1;i<=n;i++)            node[i].lson = node[i].rson = -1;        while(m--)        {            scanf("%d%d%d",&a,&b,&c);            node[a].lson = b;            node[a].rson = c;        }        int q;        scanf("%d",&q);        memset(mark,0,sizeof(mark));        for(int i = 1;i<=n;i++)            ques[i].clear();        int u,x;        for(int i = 1;i<=q;i++)        {            scanf("%d%d",&u,&x);            mark[u] =1;            ques[u].push_back(MP(x,i));            hash[n+i] = x;        }        sort(hash+1,hash+1+n+q);        tot = unique(hash+1,hash+1+n+q)-hash-1;        //printf("tot = %d\n",tot);        my_map.clear();        for(int i=1;i<=tot;i++)            my_map[hash[i]] = i;        init();        dfs(1);        for(int i = 1;i<=q;i++)        {            if(ans[i][0]==-1) puts("0");            else printf("%d %d\n",ans[i][0],ans[i][1]);        }    }    return 0;}


原创粉丝点击