hdu 4605 Magic Ball Game(离线+树状数组)

来源:互联网 发布:开发游戏的软件 编辑:程序博客网 时间:2024/05/17 19:57

题意:有T组测试数据,N表示这棵树有N个点,下一行的N个数,表示每个点的权值W,M表示边的关系,接下来的M行,每行有三个数字,u,b,b,表示点a和点b分别是点u的左儿子和右儿子。Q表示查询数,接下来的Q行,每行两个数字,v和X。

 一个权值为X球从根节点开始下落,每落到一个节点的时候,1.如果X=W[i],或者没有儿子节点了,球停止下落。2.如果X<W[i],球各有1/2的概率落到左右儿子节点。3.如果X>W[i],球有1/8的概率落到左儿子,有7/8的概率落到右儿子。问球落到点v的概率是多少(概率用7^x/2^y表示,即输出x和y就可以)?

以上复制与shiqi_614大牛关于这道题的描述。

做法我研究了许久才弄懂,一开始直接用线段树的结构去从那个点往上走,后来发觉这不是一个完全二叉树。。

做法是把树的每条链用树状数组去维护,DFS这颗树,用一种类似回朔的办法。对于权值离散化,我用的是map映射,走到某个节点,如果要往左边走,就把这个节点权值加1加入第一颗树状数组,往右走就加入第二颗,如果当前节点有询问,直接用lower_bound找到>=x的第一个值如果这个值等于x且sum(pos,0)-sum(pos-1,0)或者sum(pos,1)-sum(pos-1,1)>=1那么就说明这条链上有等于x的,就不可达到。不然就统计前缀和,代表前面有几个小于x的值,以及可以算出后面有几个大于x的值,然后计算既可。

AC代码:

#pragma comment(linker, "/STACK:102400000,102400000")#include<cstdio>#include<ctype.h>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdlib>#include<stack>#include<cmath>#include<queue>#include<set>#include<map>#include<ctime>#include<string.h>#include<string>#include<bitset>using namespace std;#define ll __int64#define eps 1e-8#define NMAX 100000+10template<class T>inline void scan_d(T &ret){    char c;    int flag = 0;    ret=0;    while(((c=getchar())<'0'||c>'9')&&c!='-');    if(c == '-')    {        flag = 1;        c = getchar();    }    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();    if(flag) ret = -ret;}int w[NMAX],a[2][NMAX],G[NMAX][2],wei[NMAX],nct,ans[NMAX][2];map<int,int>mp;vector<pair<int, int > >v[NMAX];int lowbit(int x){    return x&(-x);}int sum(int x, int flag){    int ret = 0;    while(x > 0)    {        ret += a[flag][x];        x -= lowbit(x);    }    return ret;}void add(int x, int d, int flag){    while(x <= nct)    {        a[flag][x] += d;        x += lowbit(x);    }}map<int,int>::iterator it;void dfs(int pos){    int sz = v[pos].size();    for(int i = 0; i < sz; i++)    {        int x = v[pos][i].second,k = v[pos][i].first,pp;        it = mp.lower_bound(x);//第一个>=x的        if(it == mp.end()) pp = nct+1;        else pp = it->second;        int t1 = sum(pp,0)-sum(pp-1,0),t2 = sum(pp,1)-sum(pp-1,1);        if(it->first == x && (t1 >= 1 || t2 >= 1))        {            ans[k][0] = -1;            continue;        }        t1 = sum(pp-1,0); t2 = sum(pp-1,1);        int t3 = sum(nct,0)-t1, t4 = sum(nct,1)-t2;//        cout<<x<<" "<<pp<<" "<<t1<<" "<<t2<<" "<<t3<<" "<<t4<<endl;        ans[k][0] = t2;        ans[k][1] = 3*t1+3*t2+t3+t4;    }    if(G[pos][0] == 0) return;    add(mp[w[pos]],1,0);    dfs(G[pos][0]);    add(mp[w[pos]],-1,0);    add(mp[w[pos]],1,1);    dfs(G[pos][1]);    add(mp[w[pos]],-1,1);}int main(){#ifdef GLQ    freopen("input.txt","r",stdin);//    freopen("o4.txt","w",stdout);#endif // GLQ    int t,n,m,q,i,j;    scanf("%d",&t);    while(t--)    {        mp.clear();        memset(a,0,sizeof(a));        scanf("%d",&n);        for(i = 1; i <= n; i++)            scanf("%d",&w[i]);        scanf("%d",&m);        memset(G,0,sizeof(G));        for(i = 0; i < m; i++)        {            int temp;            scanf("%d",&temp);            scanf("%d%d",&G[temp][0],&G[temp][1]);        }        memcpy(wei,w,sizeof(w));        sort(wei+1,wei+1+n);        nct = unique(wei+1,wei+n+1)-wei-1;        for(i = 1; i <= nct; i++)            mp[wei[i]] = i;        scanf("%d",&q);        for(i = 1; i <= n; i++) v[i].clear();        for(i = 0; i < q; i++)        {            int p,x;            scanf("%d%d",&p,&x);            v[p].push_back(make_pair(i,x));        }        dfs(1);        for(i = 0; i < q; i++)            if(ans[i][0] == -1) printf("0\n");            else   printf("%d %d\n",ans[i][0],ans[i][1]);    }    return 0;}


0 0
原创粉丝点击