hdu4605
Posted zsben991126
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu4605相关的知识,希望对你有一定的参考价值。
两颗线段树,分别维护向左走向右走的情况
线段树的结点维护区间有多少点被路径经过了
离线读入所有询问,dfs遍历树的每一个结点,访问到v时解决对v的所有查询,在dfs过程中只需要维护根节点到v的链,线段树查询链上有多少结点值大于或小于询问的x,即能求出到达x的概率
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<iostream> #include<stdlib.h> #include<string.h> /* 类似二叉搜索树 给定一颗n个结点的二叉树 给定数值x,从root开始沿着二叉树往下搜索,分三种情况 1.搜到叶子结点或者结点权值等于X,停止搜索 2.搜到结点权值w<x,搜索左右儿子几率各为1/2 3.w>=x,搜索左右儿子几率各为1/8,7/8 问v点被搜索到的概率是多少 两棵线段树保存向左走向右走的结果分布情况 离线+dfs */ #include<algorithm> #include<vector> #include<map> using namespace std; #define maxn 110000 #define lmin 1 #define rmax len #define lson l,(l+r)/2,rt<<1 #define rson (l+r)/2+1,r,rt<<1|1 #define root lmin,rmax,1 #define now l,r,rt #define int_now int l,int r,int rt #define INF 999999999999 #define LL long long #define mod 10007 struct list { int father; int l,r; int w; }node[maxn];//树的结点 vector<int>vec[maxn];//询问结点v的问题编号 struct listt { int x,y; int v; int w; }qq[maxn];//询问 map<int,int>mp; int len; int fs[maxn*2];//离散化后的权值 int st=0; int sum[maxn*4][2];//两棵线段树 void updata(int ll,int rr,int x,int leap,int_now) { if(ll>r||rr<l)return; if(ll<=l&&rr>=r) { sum[rt][leap]+=x; return; } updata(ll,rr,x,leap,lson); updata(ll,rr,x,leap,rson); sum[rt][leap]=sum[rt<<1][leap]+sum[rt<<1|1][leap]; } int query(int ll,int rr,int leap,int_now) { if(ll>r||rr<l)return 0; if(ll<=l&&rr>=r)return sum[rt][leap]; return query(ll,rr,leap,lson)+query(ll,rr,leap,rson); } void dfs(int x) { for(int i=0;i<vec[x].size();i++)//遍历结点x对应的每个询问 { int bi=vec[x][i]; int w=qq[bi].w; w=mp[w]; int nm=query(w,w,0,root)+query(w,w,1,root);//nm只有在走不到x结点时才非0 int ll=query(1,w-1,0,root);//root到x路径上结点权值小于w并且球向左走的点个数 int lr=query(w+1,len,0,root);//root到x路径上结点权值大于w并且球向左走的点个数 int rl=query(1,w-1,1,root);//root到x路径上结点权值小于w并且球向左走的点个数 int rr=query(w+1,len,1,root);//root到x路径上结点权值小于w并且球向左走的点个数; if(nm!=0)continue; qq[bi].x=rl; qq[bi].y=(ll+rl)*3+lr+rr; } int id=mp[node[x].w]; if(node[x].l!=0) { updata(id,id,1,0,root);//在向左走的线段树中更新当前结点的权值 dfs(node[x].l); updata(id,id,-1,0,root);//回溯,取消本次更新 } if(node[x].r!=0) { updata(id,id,1,1,root); dfs(node[x].r); updata(id,id,-1,1,root); } } int main() { int T,n,m,u,l,r; scanf("%d",&T); while(T--) { st=0; memset(sum,0,sizeof(sum)); memset(node,0,sizeof(node)); mp.clear(); scanf("%d",&n); len=0; for(int i=1;i<=n;i++) { scanf("%d",&node[i].w); fs[++st]=node[i].w; vec[i].clear(); } scanf("%d",&m); while(m--) { scanf("%d%d%d",&u,&l,&r); node[l].father=node[r].father=u; node[u].l=l; node[u].r=r; } node[1].father=-1; int q,v,ww; scanf("%d",&q); for(int i=1;i<=q;i++) { scanf("%d%d",&v,&ww); fs[++st]=ww; qq[i].v=v; qq[i].w=ww; qq[i].x=qq[i].y=-1; vec[v].push_back(i); } sort(fs+1,fs+st+1); len=0; fs[0]=-1; for(int i=1;i<=st;i++) { if(fs[i]!=fs[i-1]) { if(mp.find(fs[i])==mp.end()) { mp[fs[i]]=++len; } } } dfs(1); for(int i=1;i<=q;i++) { if(qq[i].x==-1)puts("0"); else { printf("%d %d ",qq[i].x,qq[i].y); } } } return 0; }
以上是关于hdu4605的主要内容,如果未能解决你的问题,请参考以下文章
hdu 4605 Magic Ball Game (在线主席树/离线树状数组)