树剖板子RE :( (玄2关)
  • 板块灌水区
  • 楼主AKorz
  • 当前回复6
  • 已保存回复6
  • 发布时间2024/9/10 00:02
  • 上次更新2024/9/10 18:26:44
查看原帖
树剖板子RE :( (玄2关)
716602
AKorz楼主2024/9/10 00:02
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 100009
#define lson(x) (((x)<<1)+0)
#define rson(x) (((x)<<1)+1)
#define len(l,r) ((r)-(l)+1)
struct edge{int to,nxt;}e[N];
struct node{int fa,dep,siz,son,top,dfn;}tr[N];
struct seg{int l,r,sum,tag;}st[8*N];
int n,m,u,v,z,op,rt,md,opt,cnt,a[N],w[N],head[N];
//树链剖分
void dfs1(int id,int fa,int dep)
{
	int mxsn=0;
	tr[id].fa=fa;tr[id].dep=dep;
	tr[id].siz=1;tr[id].son=0;
	for(int i=head[id];i!=-1;i=e[i].nxt)
	{
		int to=e[i].to;
		if(to==fa) continue;
		dfs1(to,id,dep+1);
		tr[id].siz+=tr[to].siz;
		if(mxsn<tr[to].siz) mxsn=tr[to].siz,tr[id].son=to;
	}
}
void dfs2(int id,int top)
{
	tr[id].dfn=++cnt;tr[id].top=top;w[cnt]=a[id];
	printf("编号%d的值为%d\n",cnt,w[cnt]);
	if(tr[id].son) dfs2(tr[id].son,top);
	for(int i=head[id];i!=-1;i=e[i].nxt)
	{
		int to=e[i].to;
		if(to==tr[id].fa||to==tr[id].son) continue;
		dfs2(to,to);
	}
}
//线段树
void build(int id,int l,int r)
{
	st[id].l=l,st[id].r=r;
	if(l==r){printf("%d is push %d\n",id,w[l]);st[id].sum=w[l];return;}
	int mid=(l+r)>>1;
	printf("%d %d %d\n",id,l,r);
	build(lson(id),l,mid);
	build(rson(id),mid+1,r);
	st[id].sum=(st[lson(id)].sum+st[rson(id)].sum)%md;
}
void pushdown(int id)
{
	st[lson(id)].sum+=st[id].tag*len(st[lson(id)].l,st[lson(id)].r);
	st[rson(id)].sum+=st[id].tag*len(st[rson(id)].l,st[rson(id)].r);
	st[lson(id)].tag=(st[lson(id)].tag+st[id].tag)%md;
	st[rson(id)].tag=(st[rson(id)].tag+st[id].tag)%md;
	st[lson(id)].sum%=md,st[rson(id)].sum%=md;
	st[id].tag=0;
}
void add(int id,int l,int r,int x,int y,int k)
{
	if(l>=x&&r<=y)
	{
		printf("%d>=%d %d<=%d 故直接加到%d\n",l,x,r,y,id);
		st[id].tag=(st[id].tag+k)%md;
		st[id].sum=(st[id].sum+k*len(st[id].l,st[id].r))%md;
		return;
	}	
	pushdown(id);
	int mid=(l+r)>>1;
	if(mid>=x) add(lson(id),l,mid,x,y,k);
	if(mid+1<=y) add(rson(id),mid+1,r,x,y,k);
	st[id].sum=(st[lson(id)].sum+st[rson(id)].sum)%md;
}
int query(int id,int l,int r,int x,int y)
{
	int res=0,mid=(l+r)>>1;
	if(l>=x&&r<=y) return st[id].sum;
	pushdown(id);
	if(mid>=x) res=(res+query(lson(id),l,mid,x,y))%md;
	if(mid+1<=y) res=(res+query(rson(id),mid+1,r,x,y))%md;
	return res;
}
//维护剖分
void upd(int x,int y,int k)
{
	while(tr[x].top!=tr[y].top)
	{
		if(tr[tr[x].top].dep<tr[tr[y].top].dep) swap(x,y);
		printf("x:%d top:%d y:%d\n",x,tr[x].top,y);
		add(1,1,n,tr[tr[x].top].dfn,tr[x].dfn,k);
		printf("已经加完\n");
		x=tr[tr[x].top].fa;
		printf("向上跳到%d\n",x);
	}
	if(tr[x].dep>tr[y].dep) swap(x,y);
	add(1,1,n,tr[x].dfn,tr[y].dfn,k);
}
int calc(int x,int y)
{
	int res=0;
	while(tr[x].top!=tr[y].top)
	{
		if(tr[tr[x].top].dep<tr[tr[y].top].dep) swap(x,y);
		printf("x:%d y:%d\n",x,y);
		res=(res+query(1,1,n,tr[tr[x].top].dfn,tr[x].dfn))%md;
		printf("已经查询完成\n");
		x=tr[tr[x].top].fa;
		printf("向上跳到%d\n",x);
	}
	if(tr[x].dep>tr[y].dep) swap(x,y);
	printf("x:%d y:%d\n",x,y);
	res=(res+query(1,1,n,tr[x].dfn,tr[y].dfn))%md;
	printf("%d %d %d\n",tr[x].dfn,tr[y].dfn,res);
	return res;
}

void check(int id)
{
	//printf("第%d个 范围%d~%d 值域%d 懒标记%d\n",id,st[id].l,st[id].r,st[id].sum,st[id].tag);
	if(st[lson(id)].l!=0) check(lson(id));
	if(st[rson(id)].l!=0) check(rson(id)); 
}

signed main()
{
	scanf("%lld%lld%lld%lld",&n,&m,&rt,&md);
	memset(head,-1,sizeof(head));opt=cnt=0;
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]%=md;
	for(int i=1;i<n;i++)
	{	
		scanf("%lld%lld",&u,&v);
		e[++opt]=(edge){v,head[u]};head[u]=opt;
		e[++opt]=(edge){u,head[v]};head[v]=opt;
	} 
	dfs1(rt,rt,1);dfs2(rt,rt);build(1,1,n);
	
	check(1);
	for(int i=1;i<=n;i++)
	{
		printf("%d:父节点%d 深度%d 字树大小%d 重儿子%d 编号%d 链顶端%d\n",i,tr[i].fa,tr[i].dep,tr[i].siz,tr[i].son,tr[i].dfn,tr[i].top);
	}
	
	for(int i=1;i<=m;i++)
	{
		scanf("%lld",&op);
		if(op==1)
		{
			scanf("%lld%lld%lld",&u,&v,&z);
			upd(u,v,z%md);
		}
		if(op==2)
		{
			scanf("%lld%lld",&u,&v);
			printf("%lld\n",calc(u,v));
		}
		if(op==3)
		{
			scanf("%lld%lld",&u,&z);
			printf("增加从%d到%d\n",tr[u].dfn,tr[u].dfn+tr[u].siz-1);
			add(1,1,n,tr[u].dfn,tr[u].dfn+tr[u].siz-1,z%md);
		}
		if(op==4)
		{
			scanf("%lld",&u);
			printf("%lld\n",query(1,1,n,tr[u].dfn,tr[u].dfn+tr[u].siz-1));
		}
		check(1);
	}
	return 0;
}

太简单的算法,发学术版怕被diss,况且灌水区的大佬多,所有为什么会RE啊?

2024/9/10 00:02
加载中...