蒟蒻刚学树剖,RE了八个点,求助
查看原帖
蒟蒻刚学树剖,RE了八个点,求助
51569
wgyhm楼主2020/7/20 14:54

蒟蒻刚学树剖,调了好久,无果后也跟题解区的DL们的代码对了好久。AC的是1,3两个点,其余全部RE。AC的两个点都跑的挺快的,我初步认为是数组的问题。

但是数组也开大了也没用,线段树和dfs也感觉没有打挂,每个数组的类型应该没错(全开long long 试了一下也是这样),请求大佬帮看。

感谢各位大佬的帮助。

Code + 一点简单的注释:

#include<bits/stdc++.h>
#define maxn 200005
#define rg register
using namespace std;
inline void read(int &x){
	int f=1;x=0;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
	x*=f;
}
inline void readl(long long &x){
	int f=1;x=0;char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
	x*=f;
}//两个快读
int son[maxn],size[maxn],id[maxn],    fa[maxn],deep[maxn],cnt,     top[maxn];
//重儿子    ,子树大小  ,再次标的序号,爸爸 ,深度      ,标号下标,重链顶端
int n,m,root;
long long mod,zz[maxn],w[maxn];
struct node{
	long long sum,add;
}f[maxn<<2];
int T,h[maxn];
struct yyy{
	int to,z;
	inline void add(int x,int y){
		to=y;z=h[x];h[x]=T;
	}
}a[maxn<<1];//链式前向星
long long k;int head,tail;
inline void Pushup(int rt){f[rt].sum=f[rt<<1].sum+f[rt<<1|1].sum;f[rt].sum%=mod;}
inline void Pushdown(int l,int r,int rt){
	if (f[rt].add){
		int m=l+r>>1;
		f[rt<<1].add+=f[rt].add;f[rt<<1|1].add+=f[rt].add;
		f[rt<<1].add%=mod;f[rt<<1|1].add%=mod;
		f[rt<<1].sum+=f[rt].add*(m-l+1);f[rt<<1].sum%=mod;
		f[rt<<1|1].sum+=f[rt].add*(r-m);f[rt<<1|1].sum%=mod;
		f[rt].add=0;
	}
}//下推标记
inline void Build(int l,int r,int rt){
	if (l==r){
		f[rt].sum=w[l];
		return;
	}
	int m=l+r>>1;
	Build(l,m,rt<<1);
	Build(m+1,r,rt<<1|1);
	Pushup(rt);
	return;
}//建树
inline void Update(int l,int r,int rt){
	if (head<=l&&r<=tail){
		f[rt].add+=k;f[rt].add%=mod;
		f[rt].sum+=k*(r-l+1);f[rt].sum%=mod;
		return;
	}
	Pushdown(l,r,rt);
	int m=l+r>>1;
	if (head<=m) Update(l,m,rt<<1);
	if (tail>m) Update(m+1,r,rt<<1|1);
	Pushup(rt);
	return;
}//更新
inline long long Query(int l,int r,int rt){
	if (head<=l&&r<=tail) return f[rt].sum%mod;
	Pushdown(l,r,rt);
	int m=l+r>>1;long long ans=0;
	if (head<=m) ans+=Query(l,m,rt<<1);
	if (tail>m) ans+=Query(m+1,r,rt<<1|1);
	return ans%mod;
}//询问
//递归式线段树
inline void dfs1(int x,int pre){
	rg int i,Max=0;
	deep[x]=deep[pre]+1;size[x]=1;fa[x]=pre;
	for (i=h[x];i+1;i=a[i].z)
		if (a[i].to!=pre){
			dfs1(a[i].to,x);size[x]+=size[a[i].to];
			if (size[a[i].to]>Max) Max=size[a[i].to],son[x]=a[i].to;
		}
}
inline void dfs2(int x,int v){
	top[x]=v;id[x]=++cnt;w[cnt]=zz[x];
	rg int i;
	if (!son[x]) return;
	dfs2(son[x],v);
	for (i=h[x];i+1;i=a[i].z)
		if (a[i].to!=son[x]&&a[i].to!=fa[x])
			dfs2(a[i].to,a[i].to);
}//树剖预处理
inline void Add1(int x,int y,long long z){
	k=z;
	while (top[x]^top[y]){
		if (deep[x]<deep[y]) x^=y^=x^=y;
		head=id[top[x]];tail=id[x];Update(1,n,1);
		x=fa[top[x]];
	}
	if (deep[x]<deep[y]) x^=y^=x^=y;
	head=id[y];tail=id[x];Update(1,n,1);
}//操作1
inline long long Query1(int x,int y){
	rg long long ans=0;
	while (top[x]^top[y]){
		if (deep[x]<deep[y]) x^=y^=x^=y;
		head=id[top[x]];tail=id[x];ans+=Query(1,n,1);
		x=fa[top[x]];
	}
	if (deep[x]<deep[y]) x^=y^=x^=y;
	head=id[y];tail=id[x];ans+=Query(1,n,1);ans%=mod;
	return ans;
}//操作2
inline void Add2(int x,long long z){
	k=z;head=id[x];tail=id[x]+size[x]-1;Update(1,n,1);
}//操作3
inline long long Query2(int x){
	head=id[x];tail=id[x]+size[x]-1;
	return Query(1,n,1)%mod;
}//操作4
int main(){
	//freopen("1.in","r",stdin);
	memset(h,-1,sizeof(h));
	rg int i,x,y,op;rg long long z;
	read(n);read(m);read(root);readl(mod);
	for (i=1;i<=n;i++) readl(zz[i]),zz[i]%=mod;
	for (i=1;i<n;i++){
		read(x);read(y);
		a[++T].add(x,y);
		a[++T].add(y,x);
	}//存边
	dfs1(root,-1);dfs2(root,root),Build(1,n,1);
	for (i=1;i<=m;i++){
		read(op);
		if (op==1) read(x),read(y),readl(z),Add1(x,y,z);
		else if (op==2) read(x),read(y),printf("%lld\n",Query1(x,y));
		else if (op==3) read(x),readl(z),Add2(x,z);
		else read(x),printf("%lld\n",Query2(x));
	}
	return 0;
}
2020/7/20 14:54
加载中...