zoukankan      html  css  js  c++  java
  • luogu P2633 Count on a tree |主席树

    题目描述

    给定一棵 (n) 个节点的树,每个点有一个权值。有 (m) 个询问,每次给你 (u,v,k),你需要回答 (u ext{ xor last})(v) 这两个节点间第 (k) 小的点权。

    其中 ( ext{last}) 是上一个询问的答案,定义其初始为 (0),即第一个询问的 (u) 是明文。

    输入格式

    第一行两个整数 (n,m)

    第二行有 (n) 个整数,其中第 (i) 个整数表示点 (i) 的权值。

    后面 (n-1) 行每行两个整数 (x,y),表示点 (x) 到点 (y) 有一条边。

    最后 (m) 行每行两个整数 (u,v,k),表示一组询问。

    输出格式

    (m) 行,每行一个正整数表示每个询问的答案。


    #include<stack>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5,M=2*N,_=1e7+5;
    inline int read(){
    	int x=0; char c=getchar();
    	while(c<'0'||c>'9')c=getchar();
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
    	return x;
    }
    int nxt[M],head[N],go[M],tot;
    inline void add(int u,int v){
    	nxt[++tot]=head[u],head[u]=tot,go[tot]=v;
    	nxt[++tot]=head[v],head[v]=tot,go[tot]=u;	
    }
    int n,m,a[N],b[N];
    #define mid ((l+r)>>1)
    int root[_],ls[_],rs[_],val[_],cnt;
    inline int build(int l,int r){
    	int rt=++cnt;
    	if(l==r)return rt;
    	ls[rt]=build(l,mid);
    	rs[rt]=build(mid+1,r);
    	return rt;
    }
    int update(int p,int l,int r,int pos){
    	int rt=++cnt;
    	ls[rt]=ls[p],rs[rt]=rs[p],val[rt]=val[p]+1;
    	if(l==r)return rt;
    	if(pos<=mid)ls[rt]=update(ls[p],l,mid,pos);
    	else rs[rt]=update(rs[p],mid+1,r,pos);
    	return rt;
    }
    int query(int p1,int p2,int q1,int q2,int l,int r,int k){
    	if(l==r)return l;
    	int x=val[ls[p1]]-val[ls[p2]]+val[ls[q1]]-val[ls[q2]];
    	if(k<=x)return query(ls[p1],ls[p2],ls[q1],ls[q2],l,mid,k);
    	else return query(rs[p1],rs[p2],rs[q1],rs[q2],mid+1,r,k-x);
    }
    int f[N][21],dep[N];
    void dfs(int u,int fa){
    	dep[u]=dep[fa]+1,f[u][0]=fa;
    	for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];
    	for(int i=head[u];i;i=nxt[i]){
    		int v=go[i];
    		if(v==fa)continue;
    		root[v]=update(root[u],1,n,a[v]);
    		dfs(v,u);
    	}
    }
    int LCA(int x,int y){
    	if(dep[x]<dep[y])swap(x,y);
    	for(int i=20;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i];
    	if(x==y)return x;
    	for(int i=20;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    signed main(){
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)a[i]=b[i]=read();
    	sort(b+1,b+1+n);
    	int len=unique(b+1,b+1+n)-b-1;
    	for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+1+len,a[i])-b;
    	for(int i=1;i<n;i++)add(read(),read());
    	root[0]=build(1,n);
    	root[1]=update(root[0],1,n,a[1]);
    	dfs(1,1);
    	f[1][0]=0;
    	int u,v,k,lst=0;
    	while(m--){
    		u=read()^lst,v=read(),k=read();
    		int lca=LCA(u,v);
    		int ans=query(root[u],root[lca],root[v],root[f[lca][0]],1,n,k);
    		printf("%d
    ",b[ans]);
    		lst=b[ans];
    	}
        return 0;
    }
    
  • 相关阅读:
    ELK 5.6.8 安装部署
    Port Forwarding in Windows
    python 压缩文件为zip后删除原文件
    Windows安装nginx服务
    redis 启动停止脚本
    使用sed替换指定文件指定行的指定文本
    auto和bool
    宽字符
    函数递归
    关于主机用户名显示为"-bash-4.1$"
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/13043268.html
Copyright © 2011-2022 走看看