zoukankan      html  css  js  c++  java
  • BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树

    BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树

    题意:

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

    分析:

    每个结点开线段树,保存到根这段路径上的权值,然后类似树上差分在主席树上求第k小

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 100050
    int head[N],to[N<<1],nxt[N<<1];
    int top[N],fa[N],dep[N],son[N],siz[N],tot,cnt;
    int n,m,root[N],t[N*50],ls[N*50],rs[N*50],a[N],see;
    struct A{
    	int num,id,v;
    }d[N];
    bool cmp1(const A &x,const A &y){return x.num<y.num;}
    bool cmp2(const A &x,const A &y){return x.id<y.id;}
    inline void add(int u,int v){
    	to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
    }
    void rd(int &x){
    	int f=1;x=0;char s=getchar();
    	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    	while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}x*=f;
    }
    void dfs1(int x){
    	siz[x]=1;
    	for(int i=head[x];i;i=nxt[i])if(to[i]!=fa[x]){
    		fa[to[i]]=x;dep[to[i]]=dep[x]+1;
    		dfs1(to[i]);
    		siz[x]+=siz[to[i]];
    		if(siz[to[i]]>siz[son[x]])son[x]=to[i];
    	}
    }
    void dfs2(int x,int t){
    	top[x]=t;
    	if(son[x])dfs2(son[x],t);
    	for(int i=head[x];i;i=nxt[i])if(to[i]!=fa[x]&&to[i]!=son[x])dfs2(to[i],to[i]);
    }
    int LCA(int x,int y){
    	while(top[x]!=top[y]){
    		if(dep[top[x]]>dep[top[y]])swap(x,y);
    		y=fa[top[y]];
    	}
    	return dep[x]<dep[y]?x:y;
    }
    void insert(int x,int &y,int l,int r,int val){
    	y=++tot;
    	if(l==r){t[y]=t[x]+1;return ;}
    	int mid=l+r>>1;
    	if(val<=mid) rs[y]=rs[x],insert(ls[x],ls[y],l,mid,val);
    	else ls[y]=ls[x],insert(rs[x],rs[y],mid+1,r,val);
    	t[y]=t[ls[y]]+t[rs[y]];
    }
    int query(int x,int y,int lca,int f,int l,int r,int k){
    	if(l==r)return a[l];
    	int mid=l+r>>1,sizls=t[ls[x]]+t[ls[y]]-t[ls[lca]]-t[ls[f]];
    	if(k<=sizls) return query(ls[x],ls[y],ls[lca],ls[f],l,mid,k);
    	else return query(rs[x],rs[y],rs[lca],rs[f],mid+1,r,k-sizls);
    }
    void build(int x){
    	for(int i=head[x];i;i=nxt[i]){
    		if(to[i]!=fa[x]){
    			insert(root[x],root[to[i]],1,n,d[to[i]].v);
    			build(to[i]);
    		}
    	}
    }
    int main(){
    	rd(n);rd(m);
    	int i,x,y,k,j;
    	for(i=1;i<=n;i++) rd(d[i].num),d[i].id=i;
    	sort(d+1,d+n+1,cmp1);
    	d[0].num=-1000000;
    	for(j=0,i=1;i<=n;i++){if(d[i].num!=d[i-1].num)j++;d[i].v=j;a[j]=d[i].num;}
    	sort(d+1,d+n+1,cmp2);
    	for(i=1;i<n;i++) {
    		rd(x);rd(y);
    		add(x,y);add(y,x);
    	}
    	dep[1]=1;fa[1]=0;
    	dfs1(1);dfs2(1,1);
    	int ans=0;
    	//for(i=1;i<=n;i++) insert(root[fa[a[i]]],root[a[i]],minn,maxn,v[a[i]]);
    	insert(root[0],root[1],1,n,d[1].v);
    	build(1);
    	for(i=1;i<=m;i++) {
    		scanf("%d%d%d",&x,&y,&k);x^=ans;
    		int lca=LCA(x,y);
    		ans=query(root[x],root[y],root[lca],root[fa[lca]],1,n,k);
    		if(i<m)
    		printf("%d
    ",ans);
    		else printf("%d",ans);
    	}
    }
    
  • 相关阅读:
    【使用intellij idea14创建多Module工程---马房山网 www.mafangshan.com】
    【Zookeeper可以干什么】
    【Zookeeper是什么】
    【win10 intelij terminal 无法输入命令】
    【Information:java: javacTask: 源发行版 1.7 需要目标发行版 1.7】
    【如何用Maven创建web项目】
    【JS关键字】
    【在网页中添加滚动文字】
    【idea自动生成serialVersionUID】
    线段树扫描线求矩形面积交
  • 原文地址:https://www.cnblogs.com/suika/p/8594677.html
Copyright © 2011-2022 走看看