[LOJ2011][主席樹]SCOI2015:情報傳遞

LOJ2011

經過分析,設某個點的起始時間爲tt,當前時間爲ii,則對答案有貢獻的點需滿足it>Ci-t>C,即iC>ti-C>t
當然把簡單路徑拆成到根節點的四條路徑,那麼修改一個點會對它子樹產生影響,就可以按當前時間建主席樹搞一搞了

Code:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=2e5+5;
namespace President_tree{
	struct seg{int l,r,sum;}tr[N*50];int cnt=0;
	#define ls(k) tr[k].l
	#define rs(k) tr[k].r
	#define mid (l+r>>1)
	inline void ins(int &rt1,int rt2,int l,int r,int ql,int qr){
		tr[rt1=++cnt]=tr[rt2];
		if(ql<=l && r<=qr){++tr[rt1].sum;return;}
		if(ql<=mid) ins(ls(rt1),ls(rt2),l,mid,ql,qr);
		if(mid<qr) ins(rs(rt1),rs(rt2),mid+1,r,ql,qr);
	}
	inline int query(int rt,int l,int r,int pos){
		if(!rt) return 0;
		if(l==r) return tr[rt].sum;
		int res=0;
		if(pos<=mid) res+=query(ls(rt),l,mid,pos);
		else res+=query(rs(rt),mid+1,r,pos);
		return res+tr[rt].sum;
	}
}
using namespace President_tree;
int vis[N<<1],nxt[N<<1],head[N],tot=0;
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
int siz[N],dep[N],hson[N],fa[N];
void dfs1(int v){
	siz[v]=1;
	for(int i=head[v];i;i=nxt[i]){
		int y=vis[i];
		dep[y]=dep[v]+1;
		dfs1(y);
		siz[v]+=siz[y];
		if(siz[y]>siz[hson[v]]) hson[v]=y;
	}
}
int top[N],sign=0,dfn[N];
void dfs2(int v){
	dfn[v]=++sign;
	top[v]=v==hson[fa[v]]?top[fa[v]]:v;
	for(int i=head[v];i;i=nxt[i])
		if(!top[vis[i]]) dfs2(vis[i]);
}
inline int lca(int x,int y){
	while(top[x]!=top[y])
		dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
	return dep[x]<dep[y]?x:y;	
}
int root,rt[N],pt[N],tim[N];
int n;
inline int get(int Time,int pos){
	if(!dfn[pos] || !tim[Time]) return 0;
	return query(rt[tim[Time]],1,n,dfn[pos]);
}
int main(){
	n=read();
	for(int i=1;i<=n;i++){
		fa[i]=read();
		if(!fa[i]) root=i;
		else add(fa[i],i);
	}
	dep[1]=1;dfs1(root);top[root]=root;dfs2(root);
	int m=read();
	for(int i=1;i<=m;i++){
		tim[i]=tim[i-1];
		int op=read();
		if(op==2){
			int x=read();
			if(pt[x]) continue;
			++tim[i];pt[x]=1;
			ins(rt[tim[i]],rt[tim[i-1]],1,n,dfn[x],dfn[x]+siz[x]-1);
		}
		else{
			int x=read(),y=read(),z=read();
			int q=max(i-z-1,0);
			int lc=lca(x,y);
			cout<<dep[x]+dep[y]-dep[lc]-dep[fa[lc]]<<" ";
			cout<<get(q,x)+get(q,y)-get(q,lc)-get(q,fa[lc])<<"\n";
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章