• hdu 4605-Magic Ball Game(树状数组)


    题目大意:

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

    思路:

    用树状数组离线处理。

    摘录学长说的:

    从一根节点u到一个点v存在的是唯一的一条确定的道路。我们只需要它在这条路上往左拐的情况中w的值(X可能大于该点的权值grtL,可能小于该点的权值lessL) 往右拐的情况中w的值(X可能大于该点的权值grtR,可能小于该点的权值lessR)  那么对于这个点的询问我们就可以知道:

    x = grtR(只有它对7有贡献)  y = (lessL + lessR) + (grtL + grtR)*3; ”

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<stdio.h>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    #define maxn 100005
    struct list
    {
    	int l,r;
    	int w;
    }node[maxn];
    int fs[maxn*2];
    int fss[maxn*2];
    struct qq
    {
    	int x;
    	int id;
    }xx;
    vector<qq>num[maxn];
    int ans[maxn][2];
    int sum[maxn][2];
    int w[maxn];
    int n,m,q,len;
    int lowbit(int x)
    {
    	 return (x&(-x));
    }
    int search(int l,int r,int w)
    {
    	while(l<r)
    	{
    		int mid=(l+r)/2;
    		if(fs[mid]==w)return mid;
    		if(fs[mid]<w)l=mid+1;
    		else r=mid;
    	}
    }
    void add(int x,int bs,int num)
    {
    	for(;x<len;x+=lowbit(x))
    	{
    		sum[x][bs]+=num;
    	}
    }
    int allsum(int s,int bs)
    {
    	int ss;
    	ss=0;
    	while(s>0)
    	{
    		ss+=sum[s][bs];
    		s=s-lowbit(s);
    	}
    	return ss;
    }
    void dfs(int x)
    {
    	int s;
    	s=num[x].size();
    	for(int i=0;i<s;i++)
    	{
    		xx=num[x][i];
    		int z,id;
    		z=search(1,len,xx.x);
    		id=xx.id;
    		if(allsum(z,0)-allsum(z-1,0)+allsum(z,1)-allsum(z-1,1)>0)
    		{
    			ans[id][0]=-1;
    			continue;
    		}
    		int ll,lr,rl,rr;
    		ll=allsum(len-1,0)-allsum(z,0);
    		rl=allsum(z,0);
    		lr=allsum(len-1,1)-allsum(z,1);
    		rr=allsum(z,1);
    		ans[id][0]=rr;
    		ans[id][1]=(rl+rr)*3+ll+lr;
    	}
    	s=search(1,len,node[x].w);
    	if(node[x].l!=-1)
    	{
    		add(s,0,1);
    		dfs(node[x].l);
    		add(s,0,-1);
    	}
    	if(node[x].r!=-1)
    	{
    		add(s,1,1);
    		dfs(node[x].r);
    		add(s,1,-1);
    	}
    }
    int main()
    {
    	int T,a,b,c,i;
    	cin>>T;
    	while(T--)
    	{
    		cin>>n;
    		int ll=1;
    		memset(fs,0,sizeof(fs));
    		memset(ans,0,sizeof(ans));
    		memset(fss,0,sizeof(fss));
    		for (i = 1; i <= n; ++i) node[i].l = node[i].r = node[i].w = -1;
    		for(i=1;i<=n;i++)
    		{
    			num[i].clear();
    			scanf("%d",&w[i]);
    			node[i].w=w[i];
    			fss[ll++]=w[i];
    		}
    		cin>>m;
    		for(i=1;i<=m;i++)
    		{
    			scanf("%d%d%d",&a,&b,&c);
    			node[a].l=b;
    			node[a].r=c;
    		}
    		cin>>q;
    		for(i=1;i<=q;i++)
    		{
    			scanf("%d%d",&a,&b);
    			fss[ll++]=b;
    			xx.id=i;
    			xx.x=b;
    			num[a].push_back(xx);
    		}
    		len=1;
    		sort(fss,fss+ll);
    		for(i=1;i<ll;i++)
    			if(fss[i]!=fss[i-1])fs[len++]=fss[i];
    		dfs(1);
    		for(i=1;i<=q;i++)
    		{
    			if(ans[i][0]==-1)printf("0
    ");
    			else printf("%d %d
    ",ans[i][0],ans[i][1]);
    		}
    	}
    	return 0;
    }
    
    


  • 相关阅读:
    【通知】OK6410开发板新加5张国嵌linux视频教程光盘
    请wince驱动调试助手的作者sunrain_hjb以及wince开发者进来看看
    【学习】关于wince5.0 的.net 框架学习——.NET Compact Framework OS Design Development
    【ARM11开发板】飞凌OK6410 开发板原厂光盘资料发布更改通知
    关于wince6.0和wince5.0 驱动的位置问题
    nand flash结构以及读写分析——写的比较经典(转载)
    【转载经典】反省研发工程师的发展之路.你属于哪一种?
    【讨论】初学者拿到2440、6410 等开发板应该怎么学习?
    为啥一个晶振都要一两块钱一个?还是国产的呢?!
    【原创】关于mobile 和wince系统定制开发的最大区别
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3223575.html
Copyright © 2020-2023  润新知