HDU-4605-Magic Ball Game (離散化+樹狀陣列+離線)
阿新 • • 發佈:2018-12-13
題意:有一顆樹,每個點有一個權值,從根節點放一個求往下落,球的值小於當前節點的值,往左右兒子落的概率各為1/2,相等則會停在這個節點,球的值大於當前節點的值往做兒子落的概率是1/8,往右兒子落的概率是7/8,q此詢問,每個詢問給一個點x和值w,問這個求落到x的概率。
思路:對於詢問的每個點,只需要管跟節點到這個節點的這條鏈上的資訊,用dfs可以很方便訪問到每條鏈,把這條鏈分為向左和向右兩部分,離散化所有權值後用樹狀陣列維護每條鏈上的值的資訊,對於每個節點的詢問,只需要求出在這條鏈上值大於,等於,小於它的點各有多少個就好了,結果就很好算出來。
AC程式碼:
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; vector<int> vec,edge[maxn]; int val[maxn],vis[maxn],fa[maxn],n,root; int getid(int x) { return lower_bound(vec.begin(),vec.end(),x)-vec.begin()+1; } struct node { int v,id; node(){}; node(int vv,int iid){v=vv;id=iid;}; }ans[maxn]; vector<node> Q[maxn]; int cnt[maxn],cnt2[maxn]; void add(int x,int val,int tp) { if(tp==1){ while(x<=n){ cnt[x]+=val; x+=(x&-x); } } else{ while(x<=n){ cnt2[x]+=val; x+=(x&-x); } } } int sum(int x,int tp) { int ans=0; if(tp==1){ while(x>0){ ans+=cnt[x]; x-=(x&-x); } } else{ while(x>0){ ans+=cnt2[x]; x-=(x&-x); } } return ans; } void dfs(int p) { int num=Q[p].size(); for(int i=0;i<num;i++){ if(p==root){ ans[Q[p][i].id]=node(0,0); continue; } int w=getid(Q[p][i].v); int a=sum(n,1),b=sum(w,1),c=sum(w-1,1); a-=b;b-=c; int a2=sum(n,2),b2=sum(w,2),c2=sum(w-1,2); a2-=b2;b2-=c2; if(b||b2) ans[Q[p][i].id]=node(-1,-1); else ans[Q[p][i].id]=node(c2,a+c*3+a2+c2*3); } if(edge[p].size()){ int pos=getid(val[p]); add(pos,1,1); dfs(edge[p][0]); add(pos,-1,1); add(pos,1,2); dfs(edge[p][1]); add(pos,-1,2); } } int main() { int T; scanf("%d",&T); while(T--){ vec.clear(); memset(vis,0,sizeof(vis)); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&val[i]); vec.push_back(val[i]); edge[i].clear(); Q[i].clear(); } int m,f,u,v; scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d%d",&f,&u,&v); edge[f].push_back(u); edge[f].push_back(v); vis[u]=1; vis[v]=1; fa[u]=fa[v]=f; } int q,x; scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d%d",&x,&v); vec.push_back(v); Q[x].push_back(node(v,i)); } sort(vec.begin(),vec.end()); vec.erase(unique(vec.begin(),vec.end()),vec.end()); n=vec.size(); for(int i=1;i<=n;i++) if(vis[i]==0){ root=i;break; } dfs(root); for(int i=1;i<=q;i++){ if(ans[i].v==-1) printf("0\n"); else printf("%d %d\n",ans[i].v,ans[i].id); } } return 0; }