AIGC标识 信息学奥赛一本通1764:社会送温暖

事先说明,本文附的代码为ai生成,因为本人是初三牲,没多少时间QWQ,望理解

原题链接:https://ybt.ssoier.cn/problem_show.php?pid=1764

【题目描述】
社会送温暖有非常多的体现方式,小G正在思考其中的一种:

我们可以把社会看做一个n个节点的树,由n−1条边连接,节点从1编号,每个节点有一定财富值,用金币数描述。

每次社会送温暖时,他会选择两个节点,对链接它们的道路上的点,采用这么几种方式:

①.按顺序加金币数,第一个加a,第二个加a+d,第三个加a+2d,以此类推。

②.按顺序加金币数,第一个加a,第二个加2a,第三个加4a,以此类推。

③.按顺序改金币数,第一个改为a,第二个改为a+d,第三个改为a+2d,以此类推。

④.按顺序改金币数,第一个改为a,第二个改为2a,第三个改为4a,以此类推。

有时社会送温暖还要考虑两个点路径间的民众反映,所以会询问路径上的金币数和,你要告诉他答案模P的值。

【输入】
第一行三个数n,q,P,分别表示节点数、操作数、和模数。

接下来n−1行每行两个整数表示一条边。

接下来1行n个整数,第i个整数Ai表示这个点上初始的金币数。

接下来q行每行三个数op,u,v,表示操作类型与操作的两个点。

若op=1或op=3,则这行后还会接两个整数a和d,如题面所描述;若op=2或op=4,则这行后还会接一个整数a;若op=5,则表示询问。

【输出】
对每个询问操作输出一行作为答案。

【输入样例】

5 5 29311
1 3
5 3
4 3
3 2
24701 12247 27130 27071 4060
4 5 1 27096
4 2 3 17348
3 1 2 8785 8918
5 3 5
4 2 1 2936

【输出样例】

15488

【提示】
【数据规模】

20%的数据:\(n,q≤1000\)。

40%的数据:\(n,q≤10000\)。

另有30%的数据:树是一条链。

100%的数据:\(1≤n,q≤10^5;1≤P≤10^7;0≤A_i,d,a≤2^{31}\)。

首先,这个是一个树链剖分的题很显然可以看出来(其实是分类里写了),那我们就先进行树剖,然后把问题就转换成一个序列加或替换成一个等差数列或等比数列。

我们先考虑等差数列怎么办,离线的做法当然是差分啦,但是他要求在线,那直接用线段树,在懒更新上做文章,具体地,我们把懒更新的内容换成A,B两个懒更新数组,表示等差数列的首项和公差,然后sum线段树就直接用求和公式算。

接下来考虑下发,这也简单,因为一个等差数列+另一个等差数列还是等差数列,首项和公差直接相加就行。

覆盖就不用我多说了把,直接把sum和懒更新清空,然后赋值。

接下来就是等比数列的内容,这个可以直接从等差数列哪里类比过来,然后因为公比为2,只需要维护一个首项就完事了。

核心的解决了,难的其实是这些不核心的(毒瘤)内容。

1.他树链剖分,是有顺序的,所以要正反都开一个数组处理,但是等差数列其实可以优化一下,我们把倒着的看成公差为负的等差数列就可以了,但是等比数列不行,必须要同时维护两个数组。

2.取模要小心,必要时不要吝啬自己的代码,我当时写了有两百行给我道心写崩了。

然后就是计算一下公式,然后当模拟题来写吧。

code(AI):

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int N=100005;

ll read(){
	ll k=0,f=1;char c=getchar();
	for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
	for(;c>='0'&&c<='9';c=getchar())k=k*10+c-'0';
	return k*f;
}

int n,q;
ll P;
vector<int>G[N];
ll a[N];
int dfn[N],fa[N],dep[N],seg[N],siz[N],son[N],top[N],idx=1;
ll pw2[N];
ll sum[N<<2],A[N<<2],B[N<<2],C[N<<2],D[N<<2];

ll norm(ll x){
	x%=P;
	if(x<0)x+=P;
	return x;
}

ll ap_sum(ll x,ll d,int len){
	return (1LL*len*(2*x+1LL*(len-1)*d)/2)%P;
}

ll gp_sum(ll x,int len){
	return x*(pw2[len]-1)%P;
}

void dfs1(int u,int f){
	siz[u]=1;
	dep[u]=dep[f]+1;
	fa[u]=f;
	for(int v:G[u]){
		if(v==f)continue;
		dfs1(v,u);
		siz[u]+=siz[v];
		if(son[u]==0||siz[son[u]]<siz[v])son[u]=v;
	}
}

void dfs2(int u,int f,int t){
	seg[idx]=u;
	dfn[u]=idx++;
	top[u]=t;
	if(!son[u])return;
	dfs2(son[u],u,t);
	for(int v:G[u]){
		if(v==f||v==son[u])continue;
		dfs2(v,u,v);
	}
}

void add_lazy(int p,ll x,ll d,int len){
	sum[p]=norm(sum[p]+ap_sum(x,d,len));
	if(A[p]>=P)A[p]=P+norm(A[p]-P+x);
	else A[p]=norm(A[p]+x);
	B[p]=norm(B[p]+d);
}

void mul1_lazy(int p,ll x,int len){
	sum[p]=norm(sum[p]+gp_sum(x,len));
	C[p]=norm(C[p]+x);
}

void mul2_lazy(int p,ll x,int len){
	sum[p]=norm(sum[p]+gp_sum(x,len));
	D[p]=norm(D[p]+x);
}

void set_lazy(int p,ll x,ll d,ll c,ll e,int len){
	sum[p]=norm(ap_sum(x,d,len)+gp_sum(c,len)+gp_sum(e,len));
	A[p]=P+norm(x);
	B[p]=norm(d);
	C[p]=norm(c);
	D[p]=norm(e);
}

void down(int p,int ln,int rn){
	if(!(A[p]||B[p]||C[p]||D[p]))return;
	if(A[p]>=P){
		ll x=A[p]-P;
		set_lazy(p<<1,x,B[p],C[p],D[p]*pw2[rn]%P,ln);
		set_lazy(p<<1|1,norm(x+1LL*ln*B[p]),B[p],C[p]*pw2[ln]%P,D[p],rn);
	}
	else{
		add_lazy(p<<1,A[p],B[p],ln);
		add_lazy(p<<1|1,norm(A[p]+1LL*ln*B[p]),B[p],rn);
		mul1_lazy(p<<1,C[p],ln);
		mul1_lazy(p<<1|1,C[p]*pw2[ln]%P,rn);
		mul2_lazy(p<<1,D[p]*pw2[rn]%P,ln);
		mul2_lazy(p<<1|1,D[p],rn);
	}
	A[p]=B[p]=C[p]=D[p]=0;
}

void build(int l,int r,int p){
	A[p]=B[p]=C[p]=D[p]=0;
	if(l==r){
		sum[p]=a[seg[l]];
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,p<<1);
	build(mid+1,r,p<<1|1);
	sum[p]=norm(sum[p<<1]+sum[p<<1|1]);
}

void add(int ql,int qr,ll x,ll d,int l,int r,int p){
	if(ql<=l&&r<=qr){
		add_lazy(p,x,d,r-l+1);
	}
	else{
		int mid=(l+r)>>1;
		down(p,mid-l+1,r-mid);
		int s=max(ql,l);
		if(ql<=mid)add(ql,qr,x,d,l,mid,p<<1);
		if(qr>mid){
			int t=max(ql,mid+1);
			add(ql,qr,norm(x+1LL*(t-s)*d),d,mid+1,r,p<<1|1);
		}
		sum[p]=norm(sum[p<<1]+sum[p<<1|1]);
	}
}

void mul1(int ql,int qr,ll x,int l,int r,int p){
	if(ql<=l&&r<=qr){
		mul1_lazy(p,x,r-l+1);
	}
	else{
		int mid=(l+r)>>1;
		down(p,mid-l+1,r-mid);
		int s=max(ql,l);
		if(ql<=mid)mul1(ql,qr,x,l,mid,p<<1);
		if(qr>mid){
			int t=max(ql,mid+1);
			mul1(ql,qr,x*pw2[t-s]%P,mid+1,r,p<<1|1);
		}
		sum[p]=norm(sum[p<<1]+sum[p<<1|1]);
	}
}

void mul2(int ql,int qr,ll x,int l,int r,int p){
	if(ql<=l&&r<=qr){
		mul2_lazy(p,x,r-l+1);
	}
	else{
		int mid=(l+r)>>1;
		down(p,mid-l+1,r-mid);
		int t=min(qr,r);
		if(ql<=mid){
			int s=min(qr,mid);
			mul2(ql,qr,x*pw2[t-s]%P,l,mid,p<<1);
		}
		if(qr>mid)mul2(ql,qr,x,mid+1,r,p<<1|1);
		sum[p]=norm(sum[p<<1]+sum[p<<1|1]);
	}
}

void change(int ql,int qr,ll x,ll d,int l,int r,int p){
	if(ql<=l&&r<=qr){
		set_lazy(p,x,d,0,0,r-l+1);
	}
	else{
		int mid=(l+r)>>1;
		down(p,mid-l+1,r-mid);
		int s=max(ql,l);
		if(ql<=mid)change(ql,qr,x,d,l,mid,p<<1);
		if(qr>mid){
			int t=max(ql,mid+1);
			change(ql,qr,norm(x+1LL*(t-s)*d),d,mid+1,r,p<<1|1);
		}
		sum[p]=norm(sum[p<<1]+sum[p<<1|1]);
	}
}

void change1(int ql,int qr,ll x,int l,int r,int p){
	if(ql<=l&&r<=qr){
		set_lazy(p,0,0,x,0,r-l+1);
	}
	else{
		int mid=(l+r)>>1;
		down(p,mid-l+1,r-mid);
		int s=max(ql,l);
		if(ql<=mid)change1(ql,qr,x,l,mid,p<<1);
		if(qr>mid){
			int t=max(ql,mid+1);
			change1(ql,qr,x*pw2[t-s]%P,mid+1,r,p<<1|1);
		}
		sum[p]=norm(sum[p<<1]+sum[p<<1|1]);
	}
}

void change2(int ql,int qr,ll x,int l,int r,int p){
	if(ql<=l&&r<=qr){
		set_lazy(p,0,0,0,x,r-l+1);
	}
	else{
		int mid=(l+r)>>1;
		down(p,mid-l+1,r-mid);
		int t=min(qr,r);
		if(ql<=mid){
			int s=min(qr,mid);
			change2(ql,qr,x*pw2[t-s]%P,l,mid,p<<1);
		}
		if(qr>mid)change2(ql,qr,x,mid+1,r,p<<1|1);
		sum[p]=norm(sum[p<<1]+sum[p<<1|1]);
	}
}

int get_lca(int u,int v){
	while(top[u]!=top[v]){
		if(dep[top[u]]>dep[top[v]])u=fa[top[u]];
		else v=fa[top[v]];
	}
	return dep[u]>dep[v]?v:u;
}

void solve1(int u,int v,int op,ll x,ll d){
	int lca=get_lca(u,v),cnt=0;
	int tot=dep[u]+dep[v]-2*dep[lca]+1;
	while(top[u]!=top[lca]){
		int l=dfn[top[u]],r=dfn[u],len=r-l+1;
		if(op==1)add(l,r,norm(x+1LL*(cnt+len-1)*d),norm(-d),1,n,1);
		else if(op==2)mul2(l,r,x*pw2[cnt]%P,1,n,1);
		else if(op==3)change(l,r,norm(x+1LL*(cnt+len-1)*d),norm(-d),1,n,1);
		else change2(l,r,x*pw2[cnt]%P,1,n,1);
		cnt+=len;
		u=fa[top[u]];
	}
	if(dep[u]>=dep[lca]){
		int l=dfn[lca],r=dfn[u],len=r-l+1;
		if(op==1)add(l,r,norm(x+1LL*(cnt+len-1)*d),norm(-d),1,n,1);
		else if(op==2)mul2(l,r,x*pw2[cnt]%P,1,n,1);
		else if(op==3)change(l,r,norm(x+1LL*(cnt+len-1)*d),norm(-d),1,n,1);
		else change2(l,r,x*pw2[cnt]%P,1,n,1);
		cnt+=len;
	}
	while(top[v]!=top[lca]){
		int l=dfn[top[v]],r=dfn[v],len=r-l+1;
		tot-=len;
		if(op==1)add(l,r,norm(x+1LL*tot*d),d,1,n,1);
		else if(op==2)mul1(l,r,x*pw2[tot]%P,1,n,1);
		else if(op==3)change(l,r,norm(x+1LL*tot*d),d,1,n,1);
		else change1(l,r,x*pw2[tot]%P,1,n,1);
		v=fa[top[v]];
	}
	if(v!=lca){
		int l=dfn[lca]+1,r=dfn[v],len=r-l+1;
		tot-=len;
		if(op==1)add(l,r,norm(x+1LL*tot*d),d,1,n,1);
		else if(op==2)mul1(l,r,x*pw2[tot]%P,1,n,1);
		else if(op==3)change(l,r,norm(x+1LL*tot*d),d,1,n,1);
		else change1(l,r,x*pw2[tot]%P,1,n,1);
	}
}

ll query(int ql,int qr,int l,int r,int p){
	if(ql<=l&&r<=qr)return sum[p];
	int mid=(l+r)>>1;
	down(p,mid-l+1,r-mid);
	ll ans=0;
	if(ql<=mid)ans+=query(ql,qr,l,mid,p<<1);
	if(qr>mid)ans+=query(ql,qr,mid+1,r,p<<1|1);
	return norm(ans);
}

ll query_path(int u,int v){
	int lca=get_lca(u,v);
	ll ans=0;
	while(top[u]!=top[lca]){
		ans=norm(ans+query(dfn[top[u]],dfn[u],1,n,1));
		u=fa[top[u]];
	}
	ans=norm(ans+query(dfn[lca],dfn[u],1,n,1));
	while(top[v]!=top[lca]){
		ans=norm(ans+query(dfn[top[v]],dfn[v],1,n,1));
		v=fa[top[v]];
	}
	if(v!=lca)ans=norm(ans+query(dfn[lca]+1,dfn[v],1,n,1));
	return ans;
}

int main(){
	n=read(),q=read(),P=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		G[u].push_back(v);
		G[v].push_back(u);
	}
	for(int i=1;i<=n;i++)a[i]=norm(read());
	dfs1(1,0);
	dfs2(1,0,1);
	pw2[0]=1%P;
	for(int i=1;i<=n;i++)pw2[i]=pw2[i-1]*2%P;
	build(1,n,1);
	while(q--){
		int op=read(),u=read(),v=read();
		if(op==5)cout<<query_path(u,v)<<'\n';
		else if(op==1||op==3){
			ll x=norm(read()),d=norm(read());
			solve1(u,v,op,x,d);
		}
		else{
			ll x=norm(read());
			solve1(u,v,op,x,0);
		}
	}
	return 0;
}
posted @ 2026-09-24 23:57  DK_orz  阅读(4)  评论(0)    收藏  举报