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\n",ans);
		else printf("%d",ans);
	}
}

 

转载于:https://www.cnblogs.com/suika/p/8594677.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的高校科研信息管理系统实现了操作日志管理、字典管理、反馈管理、公告管理、科研成果管理、科研项目管理、通知管理、学术活动管理、学院部门管理、科研人员管理、管理员管理等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让高校科研信息管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值