蒟蒻想问问为什么我这个树状数组+树上差分只有30分~?
查看原帖
蒟蒻想问问为什么我这个树状数组+树上差分只有30分~?
97946
RAIH楼主2021/7/29 20:35
#include<bits/stdc++.h>
#define num 500000
//树状数组+树上差分(包含LCA)
/*
如果第i次操作是1 x,则相当于第i时刻x点开始
可以把操作1当成第i时刻的时候点x的权值从0变成了1
如果第i次操作是2 x y c,
则相当于查询链x -> y中开始时间<i-c的点的个数
等价于查询第i-c时刻链x -> y上的和
也就相当于单点修改+区间查询 
*/ 
using namespace std;
int n,q,tot=0,dfsxu=0;
int h[num],op[num],x[num],y[num],c[num],ans[num];
int p[num],d[num],f[num][40],dfn[num],t[num],sz[num];
vector<int> now[num];
struct qbl{
	int v,next;
}e[num];
void add(int u,int v){
	e[++tot].v=v;e[tot].next=h[u];h[u]=tot;
}
void dfs(int x,int fa){//一套LCA板子 
	f[x][0]=fa;d[x]=d[fa]+1;
	if(x==0) d[x]=0; 
	else dfn[x]=++dfsxu;sz[x]=1;
	//利用DFS序和差分可以将单点修改化为子树加,链上查询化为单点查询 
	for(int i=1;i<=30;i++)
		f[x][i]=f[f[x][i-1]][i-1];
	for(int i=h[x];i;i=e[i].next){
		int y=e[i].v;if(y==fa) continue;
		dfs(y,x);sz[x]+=sz[y];
	}	
}
int lca(int x,int y){
	if(d[x]<d[y]) swap(x,y);
	for(int i=30;i>=0;i--)
		if(d[f[x][i]]>=d[y]) x=f[x][i];
	if(x==y) return x;
	for(int i=30;i>=0;i--){
		if(f[x][i]!=f[y][i]){
			x=f[x][i];
			y=f[y][i];
		}
	}	
	return f[x][0];
}
//整个树状数组维护的是由DFS序为下标的树(感觉跟树剖差不多) 
int lowbit(int x){
	return x&(-x);//取二进制最末尾1 
}
void change(int x,int v){//单点修改 
	for(int i=x;i<=n;i+=lowbit(i)) t[i]+=v;
}
int query(int x){//区间求和 
	int res=0;
	while(x>=1){res+=t[x];x-=lowbit(x);}
	return res;
}
int ask(int x,int y){
	int l=lca(x,y);
	return query(dfn[x])+query(dfn[y])-query(dfn[l])-query(p[dfn[l]]); 
	//树上对点差分~?,求出在此时x - > y之间大于c的个数 
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>p[i],add(i,p[i]),add(p[i],i);
	dfs(0,0);cin>>q;//头头是0 
	for(int i=1;i<=q;i++){
		cin>>op[i];
		if(op[i]==1){
			cin>>x[i]>>y[i]>>c[i];
			if(c[i]<i) now[i-c[i]-1].push_back(i);
			//危险值大于c的只可能在i-c-1个任务以前出现
			//记录在i-c[i]-1这个时间会造成影响的时间i 
		}
		else cin>>x[i];
	}
	for(int i=1;i<=q;i++){
		if(op[i]==2){change(dfn[x[i]],1);change(dfn[x[i]]+sz[x[i]],-1);}
		//树上差分,在自己+1,而在子树的下一点-1
		for(int j=0;j<now[i].size();j++) 
			 ans[now[i][j]]=ask(x[now[i][j]],y[now[i][j]]);
		//表示这个状态下的点会对记录的时间贡献大于c的个数 
		if(op[i]==1){
			int dis=d[x[i]]+d[y[i]]-2*d[lca(x[i],y[i])]+1;
			cout<<dis<<" "<<ans[i]<<endl;
		}	 
	}
	return 0;
}
2021/7/29 20:35
加载中...