hdu 5678 ztr loves trees(dfs序、主席树静态第k大)
来源:互联网 发布:网络写手吧 编辑:程序博客网 时间:2024/04/29 01:01
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5678
题目大意:
给出一颗根为1的树,有n个点,每个点都有一个value值。然后给出n-1条边,表示有两个点之间是相连的,最后形成一颗树。然后给出m个询问,每次询问节点x以下所有节点形成的序列的中位数。
范围:
n<=10^5,m<=10^6,1<=val<=10^9。
思路:
主席树模板题。
对于节点x以下的节点形成的序列求中位数,我们很容易想到利用主席树求任意区间上的第k大来获得中位数。所以重点就是如何将节点x以下的节点构成一个序列放到区间里面。其实也很简单,因为他要的是所有子树,所以只需要一个dfs序处理出来就可以了。
注意要先预处理出n以内的所有节点的中位数,否则会超时。
代码:
#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#include<set>#include<map>#define ll __int64#define M 100005#define mod 1000000007using namespace std;int n,m;int val[M],head[M],tot,in[M],out[M],tt;int u[M*10],v[M*10],a[M*10];int T[M],lson[M*30],rson[M*30],c[M*30],cnt,kk;ll ans[M];int x[M*10];ll MM[M*10];void init_MM(){ MM[0]=1; for(int i=1;i<=1000002;i++) MM[i]=MM[i-1]*10%mod;}struct edge{ int to,next;}edge[M*10];void init_hash(){ for(int i=1;i<=n;i++) { a[i]=val[i]; } sort(val+1,val+1+n); int siz=unique(val+1,val+1+n)-val-1; kk=siz;} void add(int a,int b) { tot++; edge[tot].to=b; edge[tot].next=head[a]; head[a]=tot;} int update(int root,int pos ,int val){ int newroot=cnt++; int tmp=newroot; c[newroot]=c[root]+val; int l=1,r=kk; while(l<r) { int mid=l+r>>1; if(mid>=pos) { lson[newroot]=cnt++; rson[newroot]=rson[root]; root=lson[root]; newroot=lson[newroot]; r=mid; } else { lson[newroot]=lson[root]; rson[newroot]=cnt++; root=rson[root]; newroot=rson[newroot]; l=mid+1; } c[newroot]=c[root]+val; } return tmp;}int hash1(int x){ return lower_bound(val+1,val+1+kk,x)-val;}void dfs(int x,int la) //dfs序处理{ in[x]=++tt; T[tt]=update(T[tt-1],hash1(a[x]),1); for(int i=head[x];i!=-1;i=edge[i].next) { int yy = edge[i].to; if(yy==la)continue; dfs(yy,x); } out[x]=tt;}int build(int l,int r){ int root=cnt++; c[root]=0; int mid=l+r>>1; if(l!=r) { lson[root]=build(l,mid); rson[root]=build(mid+1,r); } return root;}int query(int l_root,int r_root,int k){ int l=1,r=kk; while(l<r) { int mid=l+r>>1; if(c[lson[r_root]]-c[lson[l_root]]>=k) { r=mid; r_root=lson[r_root]; l_root=lson[l_root]; } else { k-=(c[lson[r_root]]-c[lson[l_root]]); l=mid+1; r_root=rson[r_root]; l_root=rson[l_root]; } } return l;}int main(){ int Ti,i,j,k,ff; scanf("%d",&Ti); init_MM(); while(Ti--) { ff=0; tt=0; tot=0; memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d",&val[i]); } for(i=1;i<n;i++) { scanf("%d%d",&u[i],&v[i]); add(u[i],v[i]); add(v[i],u[i]); } init_hash(); cnt=0; T[0]=build(1,kk); dfs(1,-1); ll sum=0; for(i=1;i<=m;i++) scanf("%d",&x[i]); for(i=1;i<=n;i++) { ll temp; int left,right; left=in[i]; right=out[i]; if((left+right)%2==0) { temp=val[query(T[left-1],T[right],(left+right)/2-left+1)]; ans[i]=temp*10; } else { temp=val[query(T[left-1],T[right],(right+left)/2-left+1)]+val[query(T[left-1],T[right],(left+right)/2+1-left+1)]; ans[i]=temp*5; } } for(i=1;i<m;i++) { ll temp; sum=sum%mod+ans[x[i]]*MM[m-i-1]%mod; sum=sum%mod; } ll temp; sum=sum%mod+(ans[x[m]]/10)%mod; sum=sum%mod; if(ans[x[m]]%10)ff=1; if(ff) printf("%.1f\n",(double)sum+0.5); else printf("%.1f\n",(double)sum); } }
0 0
- hdu 5678 ztr loves trees(dfs序、主席树静态第k大)
- hdu 5678 ztr loves trees(求子树第k大 线段树套主席树)
- HDU 5678 ztr loves trees
- poj2761&&poj2104 主席树(静态区间第K大)
- 静态区间第k大(主席树)
- 主席树(静态区间第k大)
- HDU 5756 ztr loves lucky numbers (dfs)
- HDU 5676 ztr loves lucky numbers【DFS】
- HDU5678-ztr loves trees
- 主席树求静态区间第K大
- 区间第k大(主席树)
- hdu 2665 区间第K大 主席树入门
- 主席树(静态区间第k大)+poj2014+poj2761+hdu2665
- hdu 5675 ztr loves math(数学)
- HDU 5675 ztr loves math(数学)
- hdu ztr loves lucky numbers (暴搜)
- HDU 4729 An Easy Problem for Elfness (主席树,树上第K大)
- HDU 2665 Kth number(区间第K大) (离散化+主席树)
- Spark快速入门指南
- delphi 7邮件发送程序编写
- 键盘--(微机原理实验五)
- laravel应用搭建
- enable_share_from_this
- hdu 5678 ztr loves trees(dfs序、主席树静态第k大)
- ajax
- Spring缓存注解@Cache使用
- [剑指offer]二叉搜索树的第k个结点
- 图片转换工具类BitmapFactory的使用
- ORACLE JOB使用
- iOS学习之——SDWebImage
- Android中的windowSoftInputMode属性详解
- 数据库知识点2