MnZn再求助树剖板子
查看原帖
MnZn再求助树剖板子
171295
WHJ___楼主2021/3/3 20:36

RT,90分,第十个点RE

dfs1里面有问题导致停止运行,但是查不出来

#include<bits/stdc++.h>
#define I long long
#define R register
#define il inline
#define INF 0x7fffffff
#define rt return
using namespace std;
const int N=1e5+7;

I n,m,root,HgS;
I e,st[N<<1],nxt[N<<1],to[N<<1],a[N],wt[N];//链式前向星数组 
I cnt;

struct node{
	I father,size,depth,son,sz;
	I top,dfn;
	#define fa(p) tree[p].father
	#define sz(p) tree[p].sz
	#define dep(p) tree[p].depth
	#define son(p) tree[p].son
	#define top(p) tree[p].top
	#define dfn(p) tree[p].dfn
}tree[N];

struct Segment{
	I lef,rig,len;
	I tot,tag;
	#define l(p) segment[p].lef
	#define r(p) segment[p].rig
	#define len(p) segment[p].len
	#define tot(p) segment[p].tot
	#define tag(p) segment[p].tag
}segment[N<<2];

il I d(){
	I x=0,f=1;
	char c=0;
	while(!isdigit(c=getchar()))f-=(c=='-')*2;
	while(isdigit(c)){x=(x<<1)+(x<<3)+f*(c-48);c=getchar();}
	rt x;
}

il void add(I x,I y){
	to[++e]=y;
	nxt[e]=st[x];
	st[x]=e;
}//链式前向星加边(双向)
 
il I ls(I k){return k<<1;}//左儿子

il I rs(I k){return k<<1|1;}//右儿子

il void build(I id,I l,I r){ 
	len(id)=r-l+1;
	tag(id)=0;
	l(id)=l;
	r(id)=r;
	if(l==r){
		tot(id)=wt[l]%HgS;
		return;
	}
	I mid=l+r>>1;
	build(ls(id),l,mid);
	build(rs(id),mid+1,r);
	tot(id)=(tot(ls(id))+tot(rs(id)))%HgS;
}

il void change_(I id,I val_plus){
	tot(id)=(tot(id)+len(id)*val_plus%HgS)%HgS;
	tag(id)=(tag(id)+val_plus)%HgS; 
}

il void push_down(I id){
	change_(ls(id),tag(id));
	change_(rs(id),tag(id));
	tag(id)=0;
}

il I query(I x,I y,I id){
//	printf("%lld %lld %lld\n",x,y,id); 
	if(x<=l(id)&&r(id)<=y)return tot(id);
	I sum=0,mid=l(id)+r(id)>>1;
	if(tag(id))push_down(id);
	if(x<=mid)sum=(sum+query(x,y,ls(id))%HgS)%HgS;
	if(y>mid) sum=(sum+query(x,y,rs(id))%HgS)%HgS;
	return sum;
}

il void update(I x,I y,I id,I k){
	if(x<=l(id)&&r(id)<=y){
		tot(id)=(tot(id)+k*len(id)%HgS)%HgS;
		tag(id)=(tag(id)+k)%HgS;
		return ;
	}
	if(tag(id))push_down(id);
	I mid=l(id)+r(id)>>1;
	if(x<=mid)update(x,y,ls(id),k);
	if(y>mid) update(x,y,rs(id),k);
	tot(id)=(tot(ls(id))+tot(rs(id)))%HgS;
} 

il void dfs1(I x,I f,I deep){
	I son_maxn=-1,k;
	R I i;
	dep(x)=deep;
	fa(x)=f;
	sz(x)=1;
	for(i=st[x];i;i=nxt[i]){
		k=to[i];
		if(k==f)continue;
		dfs1(k,x,deep+1);
		sz(x)+=sz(k);
		if(sz(k)>son_maxn){son(x)=k;son_maxn=sz(k);}
	}
}

il void dfs2(I x,I Top){
	I y;
	R I i;
	dfn(x)=++cnt;
	wt[cnt]=a[x];
	top(x)=Top;
	if(!son(x)) return;
	dfs2(son(x),Top);
	for(i=st[x];i;i=nxt[i]){
		y=to[i];
		if(y==fa(x)||y==son(x)) continue;
		dfs2(y,y);
	}
}
 
il void update_road(I x,I y,I k){
//操作1 将树从x到y结点最短路径上所有节点的值都加上z
	while(top(x)!=top(y)){
		if(dep(top(x))<dep(top(y))) swap(x,y);
		update(dfn(top(x)),dfn(x),1,k);
		x=fa(top(x));
	}
	if(dep(x)>dep(y)) swap(x,y);
	update(dfn(x),dfn(y),1,k);
}

 
il I query_road(I x,I y){
//操作2 求树从 x到 y结点最短路径上所有节点的值之和
	I ans=0;
	while(top(x)!=top(y)){
		if(dep(top(x))<dep(top(y))) swap(x,y);
		ans=(ans+query(dfn(top(x)),dfn(x),1)%HgS)%HgS;
		x=fa(top(x));
	}
	if(dep(x)>dep(y)) swap(x,y);
	return ans=(ans+query(dfn(x),dfn(y),1)%HgS)%HgS;
}
il void update_tree(I x,I y){
//操作3 将以x为根节点的子树内所有节点值都加上y
	update(dfn(x),dfn(x)+sz(x)-1,1,y);
}

il I query_tree(I x){
//操作4 求以 x为根节点的子树内所有节点值之和
	return query(dfn(x),dfn(x)+sz(x)-1,1);
}

signed main()
{
	R I i,j;
	I opt,x,y,z;
//	freopen(".in","r",stdin);
	//freopen("ans.txt","w",stdout);
	n=d();m=d();root=d();HgS=d();
	for(i=1;i<=n;++i) a[i]=d();
	for(i=1;i<n;++i){
		x=d();y=d();
		add(x,y);
		add(y,x);
	}
	dfs1(root,0,1);
	dfs2(root,root);
	build(1,1,n);
	while(m--){
		opt=d();x=d()%HgS;
		if(opt==1){
			y=d()%HgS;z=d()%HgS;
			update_road(x,y,z);
		}
		if(opt==2){
			y=d()%HgS;
			printf("%lld\n",query_road(x,y)); 
		}
		if(opt==3){
			y=d()%HgS;
			update_tree(x,y);
		}
		if(opt==4)printf("%lld\n",query_tree(x));
	}
	rt 0;
}
2021/3/3 20:36
加载中...