ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SP10628

2022-05-07 13:36:04  阅读:159  来源: 互联网

标签:rt int SP10628 差分 rd lca 节点


SP10628 COT - Count on a tree

给定一棵有 \(n\) 个节点的数,每个点有权值,每次操作输出节点 \(u,v\) 之间的第 \(k\) 小值。

因为有静态区间第 \(k\) 小,所以考虑主席树
因为题目要求在树上操作,所以考虑树上差分
建树的过程就是跑一个 dfs,每个节点继承其父节点的权值建树。
对于一般的维护区间第 \(k\) 小的主席树,应用前缀和的思想,之后差分出 \(rt_r - rt_{l-1}\) 得到结果。
转成树上差分就变成 \(rt_u + rt_v - rt_{lca(u,v)} - rt_{fa_{lca(u,v)}}\)。
剩下的就是主席树的模板了。
具体实现看代码。

#include <bits/stdc++.h>
#define MID int m=(l+r)>>1;
#define V e[i].v
using namespace std;int rd(){
	int w=0,v=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')v=-1;c=getchar();}
	while(c>='0'&&c<='9'){w=(w<<1)+(w<<3)+(c&15);c=getchar();}return w*v;
}void wr(int x){
    char c[20];int l=0;if(x<0){putchar((1<<5)+(1<<3)+(1<<2)+1);x=~x+1;}
    do{c[l++]=x%10+(1<<4)+(1<<5); x/=10; }while(x>0);for(int i=l-1;i>=0;i--)putchar(c[i]);putchar('\n');
}const int N=2e5+100;int a[N],n,m,b[N],tot,lst,fa[N],tp,rt[N*18];struct tree{int l,r,z;}s[N*18];
struct E{int v,nt;}e[N<<1];int fir[N],c;void I(int u,int v){e[++c].v=v;e[c].nt=fir[u];fir[u]=c;}
struct ox{
	int rt=1,a,b,n,m,cnt,dep[N],dx[N],olx[N],st[N][25];void dfs(int u,int d){
		dx[u]=++cnt;olx[cnt]=u;dep[cnt]=d;
		for(int i=fir[u];i;i=e[i].nt)if(!dx[V])dfs(V,d+1),olx[++cnt]=u,dep[cnt]=d;
	}void init(){
		for(int i=1;i<=cnt;i++)st[i][0]=i;for(int j=1;j<=log2(cnt);j++)for(int i=1;i+(1<<j)-1<=cnt;i++)
		a=st[i][j-1],b=st[i+(1<<(j-1))][j-1],st[i][j]=(dep[a]<dep[b])?a:b;
	}int lca(int l,int r){
		l=dx[l],r=dx[r];if(l>r)swap(l,r);int k=log2(r-l+1);a=st[l][k],b=st[r-(1<<k)+1][k];
		return (dep[a]<dep[b])?olx[a]:olx[b];
	}
}LCA;int id(int x){return lower_bound(a+1,a+tot+1,x)-a;}int C(int t,int l,int r,int x){
	int p=++tp;s[p]=s[t];s[p].z++;if(l==r)return p;MID 
	if(x<=m)s[p].l=C(s[t].l,l,m,x);else s[p].r=C(s[t].r,m+1,r,x);return p;
}void d2(int u,int f){fa[u]=f;rt[u]=C(rt[fa[u]],1,N,id(b[u]));for(int i=fir[u];i;i=e[i].nt)if(V!=f)d2(V,u);}
int query(int a,int b,int c,int d,int l,int r,int k){
	if(l==r)return l;int e=s[s[a].l].z+s[s[b].l].z-s[s[c].l].z-s[s[d].l].z;
	MID if(e>=k)return query(s[a].l,s[b].l,s[c].l,s[d].l,l,m,k);
	else return query(s[a].r,s[b].r,s[c].r,s[d].r,m+1,r,k-e);
}int main(){
	n=rd();m=rd();for(int i=1;i<=n;i++)b[i]=rd(),a[i]=b[i];sort(a+1,a+n+1);tot=unique(a+1,a+n+1)-a-1;
	for(int i=1,u,v;i<n;i++)u=rd(),v=rd(),I(u,v),I(v,u);LCA.dfs(1,1);LCA.init();d2(1,0);
	for(int i=1,u,v,k,l;i<=m;i++)u=rd(),v=rd(),k=rd(),l=LCA.lca(u,v),wr(a[query(rt[u],rt[v],rt[l],rt[fa[l]],1,N,k)]);
}

标签:rt,int,SP10628,差分,rd,lca,节点
来源: https://www.cnblogs.com/AIskeleton/p/16242116.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有