【BZOJ4448】【SCOI2015】—情报传递(主席树)

传送门

相当于求路径上小于ik1i-k-1的值的数量
直接上主席树,带修O(nlog2n)O(nlog^2n)
发现后面的修改是不可能对前面的询问有影响

离线先把所有修改了
建树上主席树
每次找lcalca区间求一波就可以了

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
inline int read(){
	char ch=getchar();
	int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
	return res*f;
}
const int N=200005,Log=22;
int n,q,val[N];
namespace Presi_Tree{
	int siz[N*Log],tot,lc[N*Log],rc[N*Log],rt[N];
	#define mid ((l+r)>>1)
	void ins(int &u,int r1,int l,int r,int k){
		u=++tot,siz[u]=siz[r1]+1,lc[u]=lc[r1],rc[u]=rc[r1];
		if(l==r)return;
		if(k<=mid)ins(lc[u],lc[r1],l,mid,k);
		else ins(rc[u],rc[r1],mid+1,r,k);
	}
	inline void insert(int p,int pre,int k){ins(rt[p],rt[pre],1,q,k);}
	int qry(int r1,int r2,int l,int r,int k){
		if(l==r)return siz[r2]-siz[r1];
		if(k<=mid)return qry(lc[r1],lc[r2],l,mid,k);
		else return siz[lc[r2]]-siz[lc[r1]]+qry(rc[r1],rc[r2],mid+1,r,k);
	}
	inline int query(int l,int r,int k){if(k<=0)return 0;return qry(rt[l],rt[r],1,q,k);}
}
using namespace Presi_Tree;
namespace SLPF{
	int root,dep[N],fa[N],top[N],siz[N],son[N];
	vector<int> e[N];
	inline void add(int u,int v){
		e[u].pb(v);
	}
	void dfs1(int u){
		siz[u]=1,insert(u,fa[u],val[u]);
		for(int i=0;i<e[u].size();i++){
			int v=e[u][i];
			dep[v]=dep[u]+1;
			dfs1(v),siz[u]+=siz[v];
			if(siz[v]>siz[son[u]])son[u]=v;
		}
	}
	void dfs2(int u,int tp){
		top[u]=tp;
		if(son[u])dfs2(son[u],tp);
		for(int i=0;i<e[u].size();i++){
			int v=e[u][i];
			if(v==fa[u]||v==son[u])continue;
			dfs2(v,v);
		}
	}
	inline int Lca(int u,int v){
		while(top[u]!=top[v]){
			if(dep[top[u]]<dep[top[v]])swap(u,v);
			u=fa[top[u]];
		}
		return dep[u]>dep[v]?v:u;
	}
}
using namespace SLPF;
struct ask{
	int op,x,y,c;
}p[N];
inline void chemn(int &a,int b){
	a=a>b?b:a;
}
int main(){
	n=read();
	for(int i=1;i<=n;i++){
		fa[i]=read();
		if(!fa[i])root=i;
		else add(fa[i],i);
	}
	q=read();
	for(int i=1;i<=n;i++)val[i]=q;
	for(int i=1;i<=q;i++){
		p[i].op=read();
		if(p[i].op==1){
			p[i].x=read(),p[i].y=read(),p[i].c=read();
		}
		else p[i].x=read(),p[i].y=i,chemn(val[p[i].x],i);
	}
	dfs1(root),dfs2(root,root);
	for(int i=1;i<=q;i++){
		if(p[i].op==2)continue;
		int res=0,u=p[i].x,v=p[i].y,k=p[i].c;
		int lca=Lca(u,v);
		cout<<dep[u]+dep[v]-2*dep[lca]+1<<" ";
		res+=query(lca,u,i-k-1),res+=query(lca,v,i-k-1);
		res+=(val[lca]<=i-k-1);
		cout<<res<<'\n';
	}
}
posted @ 2019-03-26 21:53  Stargazer_cykoi  阅读(115)  评论(0编辑  收藏  举报