题目链接:点这里!!!!
题意:
给定一棵N(N<=1e5)节点的树,每个节点要么有两个儿子(左右两个儿子),要么没有儿子,每个节点有一个权值w[i]。
一个权值为X球从根节点开始下落,每落到一个节点的时候,
1.如果X=W[i],或者没有儿子节点了,球停止下落。
2.如果X<W[i],球各有1/2的概率落到左右儿子节点。
3.如果X>W[i],球有1/8的概率落到左儿子,有7/8的概率落到右儿子。
给你q(q<=1e5)个询问,询问中包含v,x。问你权值为x的球从根节点(根节点是1)落到v节点的概率是多少。(落不到输出0,否则概率用7^x/2^y表示,即输出x和y就可以。)
题解:
1、这道题我们可以对所有询问离线,相当于求当前节点到根节点的路径上有多少数大于它,有多少数小于它,有多少数等于它,我们可以直接用树状树状实现。
2、从根节点开始dfs,到达x节点时,取出其中的询问,树状数组里存的是根节点到father[x]中的权值,我可以快速求出其中大于、等于、小于它的数有多少。
3、这道题就OK了,具体看代码实现。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<bitset> #include<set> #include<queue> #include<stack> #include<map> #include<cstdlib> #include<cmath> #define PI 2*asin(1.0) #define LL long long #define pb push_back #define pa pair<int,int> #define clr(a,b) memset(a,b,sizeof(a)) #define lson lr<<1,l,mid #define rson lr<<1|1,mid+1,r #define bug(x) printf("%d++++++++++++++++++++%d\n",x,x) #define key_value ch[ch[root][1]][0]C:\Program Files\Git\bin const int MOD = 1E9+7; const LL N = 2e5+15; const int maxn = 5e5+15; const int letter = 130; const int INF = 1e17; const double pi=acos(-1.0); const double eps=1e-10; using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int w[N],n,m,q,ps[N],cnt; int c[2][N],ans[N][2]; vector<int>G[N]; vector<pa>que[N]; void init(){ cnt=0; clr(c,0),clr(ans,0); for(int i=0;i<N;i++) G[i].clear(),que[i].clear(); } int lowbit(int x) {return x&(-x);} void update(int i,int val,int f){ for(int x=i;x<=cnt;x+=lowbit(x)) c[f][x]+=val; } int getsum(int i,int f){ int ans=0; for(int x=i;x>0;x-=lowbit(x)) ans+=c[f][x]; return ans; } void dfs(int x){ for(int i=0;i<que[x].size();i++){ int id=que[x][i].first,pos=que[x][i].second; pos=lower_bound(ps+1,ps+cnt+1,pos)-ps; ///0 zuo 1you int lqb=getsum(cnt,0); int rqb=getsum(cnt,1); int lx=getsum(pos-1,0); ///xiaoyu int rx=getsum(pos-1,1); int ld=lqb-getsum(pos,0); int rd=rqb-getsum(pos,1); if(lx+ld+rx+rd!=lqb+rqb){ ans[id][0]=-1; continue; } ans[id][0]=rx; ans[id][1]=lx*3+rx*3+ld+rd; } for(int i=0;i<G[x].size();i++){ int vs=lower_bound(ps+1,ps+cnt+1,w[x])-ps; update(vs,1,i); dfs(G[x][i]); update(vs,-1,i); } } int main(){ int T; scanf("%d",&T); while(T--){ init(); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",w+i),ps[++cnt]=w[i]; scanf("%d",&m); for(int i=0;i<m;i++){ int u,a,b; scanf("%d%d%d",&u,&a,&b); G[u].pb(a),G[u].pb(b); } scanf("%d",&q); for(int i=1;i<=q;i++){ int id,x; scanf("%d%d",&id,&x); que[id].pb(make_pair(i,x)); ps[++cnt]=x; } sort(ps+1,ps+cnt+1); cnt=unique(ps+1,ps+cnt+1)-(ps+1); 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; } /* */
原文:http://blog.csdn.net/u014325920/article/details/51335522