树剖MLE求助。。。
查看原帖
树剖MLE求助。。。
270897
sysss楼主2022/5/17 16:41

如题,写的线段树过了线段树1的模板 但是MLE了,前9个点都AC了,最后一个不知道为什么MLE了。。。

#include <stdio.h>
#include <algorithm>
#define MAXN 100866
using namespace std;
int p; 
int w[MAXN];
int nw[MAXN];

int nid[MAXN];

//线段树部分 
struct segNode
{
	long long val,lazy;
	int l,r;
}segT[MAXN * 4 + 2];

void buildSeg(int o,int L,int R)
{
	segT[o].l = L;
	segT[o].r = R;
	if(L == R)
	{
		segT[o].val = nw[L] % p;
		return;
	}
	int m = (segT[o].l % p + ((segT[o].r % p - segT[o].l % p) / 2)) % p;
	buildSeg(2 * o,L,m);
	buildSeg(2 * o + 1,m + 1,R);
	segT[o].val = (segT[2 * o].val % p + segT[2 * o + 1].val % p) % p;
}

void spread(int o)
{
	if(!segT[o].lazy)
	return;
	segT[2 * o].val += ((segT[2 * o].r % p - segT[2 * o].l + 1 % p) * segT[o].lazy % p) % p;
	segT[2 * o].lazy += segT[o].lazy % p;
	segT[2 * o + 1].val += ((segT[2 * o + 1].r % p - segT[2 * o + 1].l % p + 1 % p) * segT[o].lazy % p) % p;
	segT[2 * o + 1].lazy += segT[o].lazy % p;
	segT[o].lazy = 0 % p;
}

void update(int o,int L,int R,int v)
{
	//if(v == 0)return;
	if(L <= segT[o].l && R >= segT[o].r)
	{
		segT[o].lazy += v % p;
		segT[o].val += ((segT[o].r % p - segT[o].l % p + 1 % p) * v % p) % p;
		return;
	}
	spread(o);
	int m = segT[o].l % p + (segT[o].r % p - segT[o].l % p) / 2;
	if(m >= L)
	{
		update(2 * o,L,R,v);
	}
	if(m < R)
	{
		update(2 * o + 1,L,R,v);
	}
	segT[o].val = segT[o * 2].val + segT[o * 2 + 1].val;
}

long long query(int o,int L,int R)
{
	long long ans = 0;
	if(L <= segT[o].l && R >= segT[o].r)
	{
		return segT[o].val % p;
	}
	spread(o);
	int m = (segT[o].l % p + (segT[o].r % p - segT[o].l % p) / 2 % p) % p;
	if(m >= L)
	{
		ans += query(2 * o,L,R) % p;
	}
	if(m < R)
	{
		ans += query(2 * o + 1,L,R) % p;
	}
	return ans % p;
}
//树链剖分部分


int hed[MAXN * 2 + 2],nxt[MAXN * 2 + 2],to[MAXN * 2 + 2],cnt = 1,pa[MAXN * 2 + 2];

void AddEdge(int u,int v)
{
	nxt[cnt] = hed[u];
	hed[u] = cnt;
	to[cnt] = v % p;
	cnt++;
}

int depth[MAXN],sonum[MAXN],son[MAXN];

//返回以该节点为根的子树的节点个数 
int dfs1(int now,int fa)
{
	pa[now] = fa;
	depth[now] = depth[fa] + 1;
	int maxsonn = 0;
	sonum[now] = 1;
	for(int i = hed[now]; i; i = nxt[i])
	{
		int y = to[i];
		if(y == fa)
		continue;
		int nsn = dfs1(y,now);
		if(nsn > maxsonn)
		{
			son[now] = y;
			maxsonn = nsn;
		}
		sonum[now] += nsn;
	} 
	return sonum[now];
}

int top[MAXN];

int idc = 1;
void dfs2(int now,int tope)
{
	nid[now] = idc;
	nw[idc] = w[now];
	idc++;
	top[now] = tope;
	if(!son[now])
	return;
	dfs2(son[now],tope);
	for(int i = hed[now]; i; i = nxt[i])
	{
		int y = to[i];
		if(y == pa[now])
		continue;
		if(y == son[now])
		continue;
		dfs2(y,y);
	}
}

//从x到y加z 
void RoadAdd(int x,int y,int z)
{
	while(top[x] != top[y])
	{
		if(depth[top[x]] < depth[top[y]])
		swap(x,y);
		update(1,nid[top[x]],nid[x],z);
		x = pa[top[x]];
	}
	if(depth[x] < depth[y])
	swap(x,y);
	update(1,nid[y],nid[x],z);
}

//查从x到y 
int RoadQuery(int x,int y)
{
	int ans = 0;
	while(top[x] != top[y])
	{
		if(depth[top[x]] < depth[top[y]])
		swap(x,y);
		ans += query(1,nid[top[x]],nid[x]) % p;
		ans %= p;
		x = pa[top[x]];
	}
	//exit(0);
	if(depth[x] < depth[y])
	swap(x,y);
	ans += query(1,nid[y],nid[x]) % p;
	return ans % p;
}

//增加以now为子树的所有节点的值和 
void SubAdd(int now,int v)
{
	update(1,nid[now],nid[now] + sonum[now] - 1,v);
}

int SubQuery(int now)
{
	return query(1,nid[now],nid[now] + sonum[now] - 1) % p;
}

int main(void)
{
	int n,m,r;
	scanf("%d%d%d%d",&n,&m,&r,&p);
	for(int i = 1; i <= n; i++)
	{
		scanf("%d",&w[i]);
	}
	for(int i = 0; i < n - 1; i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		AddEdge(x,y);
		AddEdge(y,x);
	}
	depth[r] = 1;
	
	//exit(0);
	dfs1(r,0);
	
	dfs2(r,r);
	buildSeg(1,1,n);
	
	
	//SubQuery(r);
	for(int i = 0; i < m; i++)
	{
		int op;
		scanf("%d",&op);
		if(op == 1)
		{
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			RoadAdd(x,y,z);/*
			printf("\n");
			for(int i = 1; i <= n; i++)
			{
				printf("%d ",query(1,nid[i],nid[i]));
			}
			printf("\n");*/
		}
		else
		if(op == 2)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			printf("%d\n",RoadQuery(x,y));/*
			printf("\n");
			for(int i = 1; i <= n; i++)
			{
				printf("%d ",query(1,nid[i],nid[i]));
			}
			printf("\n");*/
		}
		else
		if(op == 3)
		{
			int x,z;
			scanf("%d%d",&x,&z);
			SubAdd(x,z);/*
			printf("\n");
			for(int i = 1; i <= n; i++)
			{
				printf("%d ",query(1,nid[i],nid[i]));
			}
			printf("\n");*/
		}
		else
		{
			int x;
			scanf("%d",&x);
			printf("%d\n",SubQuery(x));/*
			printf("\n");
			for(int i = 1; i <= n; i++)
			{
				printf("%d ",query(1,nid[i],nid[i]));
			}
			printf("\n");*/
		}
	}
	return 0;
}

2022/5/17 16:41
加载中...