http://acm.hdu.edu.cn/showproblem.php?pid=4605
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 309 Accepted Submission(s): 73
思路: 首先考虑一个询问(V,X),若从根节点到V节点的路径上(不包括V)已存在权值为X的节点,则小球不可能到达V节点,否则,不妨定义往左走的路径为“左路径”,往右走的路径称为“右路径”。设lmi,lma,rmi,rma分别表示左路径上小于X的节点数,左路径上大于X的节点数,右路径上小于X的节点数,右路径上大于X的节点数,则最终的答案即为: (1/2)^(lma+rma)*(7/8)^(rmi)*(1/8)^(lmi)。即输出 rmi 和 3*(lmi+rmi)+(lma+rma)即可。
对于本题,我们可以离线处理每个节点上的询问,从根节点做一次DFS,在过程中每经过一个节点就处理该节点所对应的询问,我们可以用线段树,树状数组等数据结构记录从根节点到V的路径上所有的权值(不包括V),然后就可以得到lmi,lma,rmi,rma,剩下的就是更行答案了,另外X很大,需要离散化处理。
代码如下:
#include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #include <vector> #define maxn 100010 #define mid ((t[p].l+t[p].r)>>1) #define ls (p<<1) #define rs (ls|1) using namespace std; struct Tree { int w; int left,right; }node[maxn]; vector<int> vec[maxn]; int c[maxn<<1][2]; void init(int n) { for(int i=0;i<=n;i++) { vec[i].clear(); node[i].left=node[i].right=node[i].w=-1; } } void add(int a,int b,int c) { node[a].left=b; node[a].right=c; } int ans[maxn][2],vis[maxn],po[maxn<<1],len; int lowbit(int x) { return x&(-x); } void addnum(int x,int val,int tt) { while(x<=len) { c[x][tt]+=val; x+=lowbit(x); } } int getsum(int x,int tt) { int sum=0; while(x>0) { sum+=c[x][tt]; x-=lowbit(x); } return sum; } int search(int len,int x) { int mi=1,ma=len,Mid; while(mi<=ma) { Mid=(mi+ma)>>1; if(po[Mid]==x) return Mid; if(po[Mid]<x) mi=Mid+1; else ma=Mid-1; } } void dfs(int now) { int i,w=search(len,node[now].w); for(i=0;i<vec[now].size();i+=2) { int x=search(len,vec[now][i]),num=vec[now][i+1]; if(getsum(x,0)-getsum(x-1,0)>0||getsum(x,1)-getsum(x-1,1)>0)//如果已经存在x { ans[num][0]=-1; } else { int lma,lmi,rma,rmi;// 左边大于,左边小于,右边大于,右边小于 lmi=getsum(x-1,0); lma=getsum(len,0)-getsum(x,0); rmi=getsum(x-1,1); rma=getsum(len,1)-getsum(x,1); ans[num][0]=rmi; ans[num][1]=3*(rmi+lmi)+rma+lma; } } if(node[now].left!=-1) { addnum(w,1,0); dfs(node[now].left); addnum(w,-1,0); } if(node[now].right!=-1) { addnum(w,1,1); dfs(node[now].right); addnum(w,-1,1); } } int main() { //freopen("dd.txt","r",stdin); int ncase; scanf("%d",&ncase); while(ncase--) { int n,i,m,q,x,v; scanf("%d",&n); init(n); for(i=1;i<=n;i++) { scanf("%d",&node[i].w); po[i]=node[i].w; } scanf("%d",&m); int a,b,cc; memset(vis,0,sizeof(vis)); for(i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&cc); add(a,b,cc); vis[b]=vis[cc]=1; } scanf("%d",&q); for(i=1;i<=q;i++) { scanf("%d%d",&v,&x); vec[v].push_back(x); vec[v].push_back(i); po[i+n]=x; } sort(po+1,po+q+n+1); len=unique(po+1,po+q+n+1)-(po+1); int root; for(i=1;i<=n;i++) { if(!vis[i]) { root=i; break; } } for(i=0;i<=len;i++) c[i][0]=c[i][1]=0; dfs(root); for(i=1;i<=q;i++) { if(ans[i][0]==-1) printf("0\n"); else printf("%d %d\n",ans[i][0],ans[i][1]); } } return 0; }