悬关求调10pts树链剖分
查看原帖
悬关求调10pts树链剖分
1023793
yaodiguoan楼主2024/10/20 21:21

recordrecord

#include <bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
//#pragma GCC optimize(3, "Ofast", "inline")
#define hh putchar('\n')
#define kg putchar(' ')
#define debug puts("debug")
//#define int long long
//#define int __int128
namespace quickread{
	template<typename T> void read(T &x){
		x=0;char c=getchar();T neg=0;
		while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
		while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
		if(neg) x=(~x)+1;
	}
	template<typename T> void write(T x){
		if(x<0) putchar('-'),x=~x+1;
		if(x>9) write(x/10);
		putchar(x%10^48);
	}
}
using namespace quickread;
const int N=1e6+10,inf=2147483647;
int n,m,root,a[N],b[N],mod;
#define ls (p<<1)
#define rs (p<<1|1)
#define mid (l+r>>1)
struct node{int value,tag;};
node segment_tree[N];
void push_up(int p){segment_tree[p].value=(segment_tree[ls].value+segment_tree[rs].value)%mod;}
void push_down(int l,int r,int p){
	if(!segment_tree[p].tag) return void();
	segment_tree[ls].tag+=segment_tree[p].tag,segment_tree[rs].tag+=segment_tree[p].tag;
	segment_tree[ls].value+=(mid-l+1)*segment_tree[p].tag,segment_tree[rs].value+=(r-mid)*segment_tree[p].tag;
	segment_tree[ls].value%=mod,segment_tree[rs].value%=mod;
	segment_tree[p].tag=0;
}
void build(int l,int r,int p){
	segment_tree[p]=node{0,0};
	if(!(l^r)) return segment_tree[p].value=b[l]%mod,void();
	build(l,mid,ls),build(mid+1,r,rs);
	push_up(p);
}
void update(int lt,int rt,int l,int r,int p,int x){
	if(lt<=l&&r<=rt) return segment_tree[p].tag+=x,segment_tree[p].value+=(r-l+1)*x,segment_tree[p].value%=mod,void();
	push_down(l,r,p);
	if(lt<=mid) update(lt,rt,l,mid,ls,x);
	if(rt>mid) update(lt,rt,mid+1,r,rs,x);
	push_up(p); 
}
int query(int lt,int rt,int l,int r,int p){
	if(lt<=l&&r<=rt) return segment_tree[p].value;
	push_down(l,r,p);
	int ans=0;
	if(lt<=mid) ans+=query(lt,rt,l,mid,ls);
	if(rt>mid) ans+=query(lt,rt,mid+1,r,rs);
	return ans;
}
int num,son[N],id[N],fa[N],dep[N],siz[N],top[N];
vector<int> tree[N];
void dfs1(int u,int f){
	dep[u]=dep[f]+1;
	fa[u]=f;
	siz[u]=1;
	for(int v:tree[u])
		if(v^f){
			dfs1(v,u);
			siz[u]+=siz[v];
			if(!son[u]||siz[son[u]]<siz[v]) son[u]=v;
		}
}
void dfs2(int u,int topx){
	id[u]=++num;a[num]=b[u];
	top[u]=topx;
	if(!son[u]) return void();
	dfs2(son[u],topx);
	for(int v:tree[u])
		if(v^fa[u]&&v^son[u]) dfs2(v,v);
}
void update_range(int x,int y,int z){
	while(top[x]^top[y]){
		if(dep[top[y]]<dep[top[y]]) swap(x,y);
		update(id[top[x]],id[x],1,n,1,z);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	update(id[x],id[y],1,n,1,z);
}
int query_range(int x,int y){
	int ans=0;
	while(top[x]^top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		ans=(ans+query(id[top[x]],id[x],1,n,1))%mod;
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	ans+=query(id[x],id[y],1,n,1);
	return ans%mod;
}
signed main(){
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);
	read(n),read(m),read(root),read(mod);
	for(int i=1;i<=n;++i) read(b[i]);
	for(int i=1,u,v;i<n;++i) read(u),read(v),tree[u].push_back(v),tree[v].push_back(u);
	dfs1(root,0),dfs2(root,root),build(1,n,1);
	for(int i=1,opt,x,y,z;i<=m;++i){
		read(opt);
		if(opt==1) read(x),read(y),read(z),update_range(x,y,z);
		else if(opt==2) read(x),read(y),write(query_range(x,y)),hh;
		else if(opt==3) read(x),read(y),update(id[x],id[x]+siz[x]-1,1,n,1,y);
		else read(x),write(query(id[x],id[x]+siz[x]-1,1,n,1)%mod),hh;
	}
	return 0;
}


2024/10/20 21:21
加载中...