题目链接:点这里!!!!
题意:
给定一棵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;
}
/*
*/