zoukankan      html  css  js  c++  java
  • BZOJ2588: Spoj 10628. Count on a tree(主席树)


    BZOJ2588: Spoj 10628. Count on a tree##

      Time Limit: 12 Sec
      Memory Limit: 128 MB

    Description###

       给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
     

    Input###

       第一行两个整数N,M。
       第二行有N个整数,其中第i个整数表示点i的权值。
       后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
       最后M行每行两个整数(u,v,k),表示一组询问。
     

    Output###

       M行,表示每个询问的答案。最后一个询问不输出换行符
     

    Sample Input###

      8 5
      105 2 9 3 8 5 7 7
      1 2
      1 3
      1 4
      3 5
      3 6
      3 7
      4 8
      2 5 1
      0 5 2
      10 5 3
      11 5 4
      110 8 2
     

    Sample Output###

      2
      8
      9
      105
      7
        

    HINT

       N,M<=100000
       暴力自重。。。
      

    题目地址:BZOJ2588: Spoj 10628. Count on a tree

    题目大意: 已经很简洁了

    题解:

      主席树
      先对所有点权离散化一遍(因为要建权值线段树)
      然后对树上的每一个节点到根的路径建一棵权值线段树
      然后空间为 (n^2log_{2}n)  显然 (MLE)
      因为这些树形态结构都是一样的
      而且对于每个非根节点
      他所构成的权值线段树只与他父亲差了一个数(他自己的点权)
      所以可以按 (dfs) 序来建主席树,进行加减运算(主席树特性)
      那么x,y两点之间的路径上所构成的权值线段树就可以表示成

    [Tree[x]+Tree[y]-Tree[lca(x,y)]-Tree[fa[lca(x,y)] ]

      (画图验证)
      具体看代码


    AC代码

    #include <cstdio> 
    #include <algorithm>
    #include <map>
    using namespace std;
    const int N=1e5+5,M=18e5+5;
    int n,Q,New,cnt,ans;
    int last[N],val[N],hash[N];
    int rt[N],ls[M],rs[M],sum[M];
    map<int,int> mp;
    struct edge{
    	int to,next;
    }e[N<<1];
    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;
    }
    inline void add_edge(int u,int v){
    	e[++cnt]=(edge){v,last[u]};last[u]=cnt;
    	e[++cnt]=(edge){u,last[v]};last[v]=cnt;
    }
    int ind,pos[N],sop[N],dep[N],fa[N][18];
    void dfs(int u){
    	pos[u]=++ind;
    	sop[ind]=u;
    	for(int i=last[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==fa[u][0])continue;
    		fa[v][0]=u;
    		dep[v]=dep[u]+1;
    		dfs(v);
    	}
    }
    int lca(int a,int b){
    	if(dep[a]<dep[b])swap(a,b);
    	for(int i=17;i>=0;i--)
    		if(dep[fa[a][i]]>=dep[b])
    			a=fa[a][i];
    	for(int i=17;i>=0;i--)
    		if(fa[a][i]!=fa[b][i])
    			a=fa[a][i],b=fa[b][i];
    	if(a==b)return a;
    	return fa[a][0];
    }
    int sz;
    void build(int l,int r,int pre,int &now,int num){
    	now=++sz;
    	sum[now]=sum[pre]+1;
    	if(l==r)return;
    	ls[now]=ls[pre];
    	rs[now]=rs[pre];
    	int mid=(l+r)>>1;
    	if(num<=mid)build(l,mid,ls[pre],ls[now],num);
    	else build(mid+1,r,rs[pre],rs[now],num);
    }
    int solve(int u,int v,int rk){
    	int a=u,b=v,c=lca(u,v),d=fa[c][0];
    	a=rt[pos[a]],b=rt[pos[b]],c=rt[pos[c]],d=rt[pos[d]];
    	int l=1,r=New;
    	while(l<r){
    		int mid=(l+r)>>1;
    		int tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]];
    		if(tmp>=rk){
    			r=mid;
    			a=ls[a],b=ls[b],c=ls[c],d=ls[d];
    		}else{
    			l=mid+1;rk-=tmp;
    			a=rs[a],b=rs[b],c=rs[c],d=rs[d];
    		}
    	}
    	return hash[l];
    }
    int main(){
    	n=read();Q=read();
    	for(int i=1;i<=n;i++)
    		val[i]=hash[i]=read();
    	sort(hash+1,hash+n+1);
    	New=unique(hash+1,hash+n+1)-hash-1;
    	for(int i=1;i<=New;i++)
    		mp[hash[i]]=i;
    	for(int i=1;i<=n;i++)
    		val[i]=mp[val[i]];
    	for(int i=1;i<n;i++){
    		int u=read(),v=read();
    		add_edge(u,v);
    	}
    	dep[1]=1;
    	dfs(1);
    	for(int j=1;j<=17;j++)
    		for(int i=1;i<=n;i++)
    			fa[i][j]=fa[fa[i][j-1]][j-1];
    	for(int i=1;i<=n;i++)
    		build(1,New,rt[pos[fa[sop[i]][0]]],rt[i],val[sop[i]]);
    	while(Q--){
    		int u=read()^ans,v=read(),rk=read();
    		ans=solve(u,v,rk);
    		printf("%d",ans);
    		if(Q)puts("");
    	}
    	return 0;
    }
    


      作者:skl_win
      出处:https://www.cnblogs.com/shaokele/
      本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    在日本被禁止的コンプガチャ設計
    Starling常见问题解决办法
    Flixel引擎学习笔记
    SQLSERVER中修复状态为Suspect的数据库
    T4 (Text Template Transformation Toolkit)实现简单实体代码生成
    创建Linking Server in SQL SERVER 2008
    Linq to Sql 与Linq to Entities 生成的SQL Script与分页实现
    Linq to Entity 的T4 模板生成代码
    在VisualStudio2008 SP1中调试.net framework 源代码
    使用HttpModules实现Asp.net离线应用程序
  • 原文地址:https://www.cnblogs.com/shaokele/p/9514445.html
Copyright © 2011-2022 走看看