树链剖分板子30pts求调
查看原帖
树链剖分板子30pts求调
609092
ben090302楼主2023/1/7 13:24

数据点1 3 4过了,其他的提示在xx行无输出,是树状数组写法,调了半天没调出来,求救

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=100010;
struct gr{//链式前向星存图 
	int to,nxt;
}g[maxn*2]; 
int tot,head[maxn],c[maxn],t[maxn];
int fa[maxn],dep[maxn],son[maxn],siz[maxn],top[maxn],dfn[maxn],w[maxn],tim,v[maxn];

void adeg(int u,int v){
	g[++tot].to=v;
	g[tot].nxt=head[u];
	head[u]=tot;
}

int n,m,r,p;

int lb(int x){
	return x&(-x);
}

void build(){
	for(int i=1;i<=n;i++){
	   int prt=w[i]-w[i-1];
	   c[i]+=prt,t[i]+=prt*(i-1);
	   if(i+lb(i)<=n) c[i+lb(i)]+=c[i],t[i+lb(i)]+=t[i];
	}
}

void add(int x,int k){
	for(int i=x;i<=n;i+=lb(i))c[i]+=k,t[i]+=k*(x-1);
}

int query(int x){
	int ret=0;
	for(int i=x;i;i-=lb(i)) ret+=x*c[i]-t[i],ret%=p;
	return (ret+p)%p;
}


void dfs1(int u,int f){//u=当前节点,f=u的跌 
	fa[u]=f;
	dep[u]=dep[f]+1;
	siz[u]=1;
	int msize=-1;
	for(int i=head[u];i;i=g[i].nxt){
		int v=g[i].to;
		if(v==f) continue;
		dfs1(v,u);
		siz[u]+=siz[v];
		if(siz[v]>msize){
			msize=siz[v];
			son[u]=v;
		}
	}
}

void dfs2(int u,int tp){//u为当前节点,t为当前链的顶端 
	dfn[u]=++tim;
	top[u]=tp;
	w[tim]=v[u];
	if(!son[u]) return;
	dfs2(son[u],tp);
	for(int i=head[u];i;i=g[i].nxt){
		int v=g[i].to;
		if(v==fa[u] or v==son[u]) continue;
		dfs2(v,v);
	}
}

void mson(int x,int z){//修改子树 操作3 
	add(dfn[x],z);
	add(dfn[x]+siz[x],-z);
}

int qson(int x){//查询子树 操作4 
	return (query(dfn[x]+siz[x]-1)-query(dfn[x]-1)+p)%p;
}

void mline(int x,int y,int z){//修改x到y最短路径 操作1 
	z%=p;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		add(dfn[top[x]],z),add(dfn[x]+1,-z);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	add(dfn[x],z),add(dfn[y]+1,-z);
}

int qline(int x,int y){//查询x到y最短路径 操作2 
	int ret=0;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		ret+=query(dfn[x])-query(dfn[top[x]]-1);
		ret%=p;
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	ret+=query(dfn[y])-query(dfn[x]-1);
	return (ret+p)%p;
}

signed main(){
	cin>>n>>m>>r>>p;
	for(int i=1;i<=n;i++) cin>>v[i];
	for(int i=1;i<n;i++){
		int u,v;
		cin>>u>>v;
		adeg(u,v),adeg(v,u);
	}
	dfs1(r,r),dfs2(r,r);
	build();//树状数组预处理 
	while(m--){
		int mt,x,y,z;
		cin>>mt;
		if(mt==1) cin>>x>>y>>z,mline(x,y,z);
		else if(mt==2) cin>>x>>y,cout<<qline(x,y)<<"\n";
		else if(mt==3) cin>>x>>z,mson(x,z);
		else cin>>x,cout<<qson(x)<<"\n";
	}
}

2023/1/7 13:24
加载中...