zoukankan      html  css  js  c++  java
  • P2633 Count on a tree

    P2633 Count on a tree

    P2633 Count on a tree

    给定一棵树,询问树上两点路径的第 k 小,强制在线。

    可以直接树剖然后主席树,复杂度俩 (log)

    这里主要是一个数据结构维护树上前缀信息的技巧。

    想一想我们求树上两点距离怎么求的?

    (dist(u,v)=dis(u)+dis(v)-2*dis(lca))

    这里 (dis) 指的是到根节点的距离。

    这里我们通过维护一个前缀距离,再在树上进行差分,就达到了目的。

    那么我们可不可以把这个“距离”改造成“树”来更好地维护更多的信息呢?

    显然是可以的,但是我们显然不能把每棵树直接建出来,再加上这个是前缀信息,这让我们想到了什么呢?

    ——可持久化数据结构。

    我们发现主席树维护的是 sum (这个值域的数的总数),这个具有可减性,那么我们可以考虑这样在主席树上二分找第 k 大即可:

    在每一个节点,其基准值就是 (sum(lc(u))+sum(lc(v))-sum(lc(lca))-sum(lc(falca))) ,其中所有 (u,v,lca,falca) 代表的是当前的四个节点对应的主席树节点。

    那么这道题这样就很简单了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
    	x=0;char ch=getchar();bool f=false;
    	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
    	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	x=f?-x:x;
    	return ;
    }
    template <typename T>
    inline void write(T x){
    	if(x<0) putchar('-'),x=-x;
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    	return ;
    }
    const int N=4e5+5,NN=1e8;
    int n,m,q,a[N],root[N],cur,Idx,b[N];
    int nex[N<<1],to[N<<1],head[N],idx;
    int fa[N][18],dep[N],Fa[N],siz[N];
    inline int Getfa(int x){return x==Fa[x]?x:Fa[x]=Getfa(Fa[x]);}
    inline void add(int u,int v){
    	nex[++idx]=head[u];
    	to[idx]=v;
    	head[u]=idx;
    	return ;
    }
    struct SGTree{
    	int lc,rc,val,sum;
    	#define lc(x) t[x].lc
    	#define rc(x) t[x].rc
    	#define val(x) t[x].val
    	#define sum(x) t[x].sum
    }t[NN];
    inline void Pushup(int x){sum(x)=sum(lc(x))+sum(rc(x));return ;}
    void Modify(int &x,int pre,int l,int r,int pos,int v){
    	x=++cur;
    	t[x]=t[pre];sum(x)++;
    	if(l==r) return ;
    	int mid=(l+r)>>1;
    	if(pos<=mid) Modify(lc(x),lc(pre),l,mid,pos,v);
    	else Modify(rc(x),rc(pre),mid+1,r,pos,v);
    	return ;
    }
    inline void Update(int x,int f){
    	fa[x][0]=f;dep[x]=dep[f]+1;
    	for(int i=1;i<=16;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    	Modify(root[x],root[f],1,Idx,a[x],1);
    	return ;
    }
    int QueryLca(int u,int v){
    	if(dep[u]<dep[v]) swap(u,v);
    	for(int i=16;i>=0;i--) if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];
    	if(u==v) return u;
    	for(int i=16;i>=0;i--) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
    	return fa[u][0];
    }
    int QueryKth(int u,int v,int lca,int falca,int l,int r,int k){
    	if(l==r) return l;
    	int mid=(l+r)>>1,lsum=sum(lc(u))+sum(lc(v))-sum(lc(lca))-sum(lc(falca));
    	if(k<=lsum) return QueryKth(lc(u),lc(v),lc(lca),lc(falca),l,mid,k);
    	else return QueryKth(rc(u),rc(v),rc(lca),rc(falca),mid+1,r,k-lsum);
    }
    void Build(int x,int f){
    	Update(x,f);
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(y==f) continue;
    		Build(y,x);
    	}
    	return ;
    }
    void Link(int u,int v){
    	int x=Getfa(u),y=Getfa(v);
    	if(siz[x]<siz[y]) swap(u,v),swap(x,y);
    	siz[x]+=siz[y],Fa[y]=x;
    	add(u,v),add(v,u);
    	Build(v,u);
    	return ;
    }
    bool vis[N];
    void dfs(int x,int f){
    	vis[x]=true;Update(x,f);
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(y==f) continue;
    		dfs(y,x);
    	}
    	return ;
    }
    int main(){
    	read(n),read(m);
    	for(int i=1;i<=n;i++) read(a[i]),Fa[i]=i,siz[i]=1,b[i]=a[i];
    	sort(b+1,b+n+1);Idx=unique(b+1,b+n+1)-b-1;
    	for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+Idx+1,a[i])-b,Modify(root[i],0,1,Idx,a[i],1);
    	for(int i=1;i<n;i++){
    		int u,v;
    		read(u),read(v);
    		add(u,v);add(v,u);
    	}
    	for(int i=1;i<=n;i++) if(!vis[i]) dfs(i,0);
    	int las=0;
    	for(int i=1;i<=m;i++){
    		int u,v,w;
    		read(u),read(v),read(w);
    		u^=las;int LCA=QueryLca(u,v);
    		las=b[QueryKth(root[u],root[v],root[LCA],root[fa[LCA][0]],1,Idx,w)];
    		write(las),putchar('
    ');
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    关于拉格朗日乘子法和KKT条件
    深入理解拉格朗日乘子法(Lagrange Multiplier) 和KKT条件
    安全模式下运行Windows installer并卸载程序
    win10 进入安全模式的方法
    支持向量机通俗导论(理解SVM的三层境界)
    Windows系统防火墙用法
    浏览器起始页被篡改恶意跳转解决方法
    网络熟知端口号
    SSL/TLS协议运行机制的概述
    分布式拒绝服务攻击 DDoS
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14649639.html
Copyright © 2011-2022 走看看