wuhualin0401 @ 2024-08-29 21:54:10
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 200005
int n,m,r,p,cnt;
int fa[N],top[N],hson[N],siz[N],dep[N],id[N],a[N],w[N],f[N * 4],lazy[N * 4];
vector<int>e[N * 2];
int read(){
int a;
scanf("%lld",&a);
return a;
}
void dfs1(int k,int f){
siz[k] = 1;
dep[k] = dep[f] + 1;
fa[k] = f;
for(int i = 0;i < e[k].size();i++){
int v = e[k][i];
if(v == f) continue;
dfs1(v,k);
siz[k] += siz[v];
if(siz[hson[k]] < siz[v]){
hson[k] = v;
}
}
return;
}
void dfs2(int k,int t){
top[k] = t;
id[k] = ++cnt;
w[cnt] = a[k];
if(hson[k])
dfs2(hson[k],t);
for(int i = 0;i < e[k].size();i++){
int v = e[k][i];
if(v == hson[k] || v == fa[k]) continue;
dfs2(v,v);
}
return;
}
void build(int k,int l,int r){
if(l == r){
f[k] = w[l];
return;
}
int mid = (l + r) / 2;
build(k * 2,l,mid);
build(k * 2 + 1,mid + 1,r);
f[k] = f[k * 2] + f[k * 2 + 1];
}
void change(int k,int l,int r,int v){
lazy[k] = (lazy[k] + v) % p;
f[k] = (f[k] + v * (r - l + 1) % p) % p;
return;
}
void spread(int k,int l,int r){
if(!lazy[k]) return;
int mid = (l + r) / 2;
change(k * 2,l,mid,lazy[k]);
change(k * 2 + 1,mid + 1,r,lazy[k]);
lazy[k] = 0;
}
void add(int k,int l,int r,int x,int y,int v){
if(x <= l && r <= y){
lazy[k] = (v + lazy[k]) % p;
f[k] = (f[k] + ((r - l + 1) * v) % p) % p;
return;
}
else{
spread(k,l,r);
int mid = (l + r) / 2;
if(x <= mid) add(k * 2,l,mid,x,y,v);
if(y > mid) add(k * 2 + 1,mid + 1,r,x,y,v);
f[k] = (f[k * 2] + f[k * 2 + 1]) % p;
}
}
int query(int k,int l,int r,int x,int y){
if(x <= l && r <= y){
return f[k];
}
int mid = (l + r) / 2,ans = 0;
spread(k,l,r);
if(x <= mid) ans = (ans + query(k * 2,l,mid,x,y)) % p;
if(y > mid) ans = (ans + query(k * 2 + 1,mid + 1,r,x,y)) % p;
return ans;
}
int lca(int x,int y,int v){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]])
swap(x,y);
add(1,1,n,id[top[x]],id[x],v);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
add(1,1,n,id[x],id[y],v);
}
int ask1(int k,int l,int r,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(1,1,n,id[top[x]],id[x])) % p;
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
ans = (ans + query(1,1,n,id[x],id[y])) % p;
return ans;
}
signed main(){
n = read(),m = read(),r = read(),p = read();
for(int i = 1;i <= n;i++)
a[i] = read() % p;
for(int i = 1;i <= n - 1;i++){
int u,v;
u = read();
v = read();
e[u].push_back(v);
e[v].push_back(u);
}
dfs1(r,0);
dfs2(r,0);
build(1,1,n);
for(int i = 1;i <= m;i++){
int op;
op = read();
if(op == 1){
int x,y,z;
x = read(),y = read(),z = read() % p;
lca(x,y,z);
}
if(op == 2){
int x,y,z;
x = read(),y = read();
printf("%lld\n",ask1(1,1,n,x,y));
}
if(op == 3){
int x,z;
x = read(),z = read();
add(1,1,n,id[x],id[x] + siz[x] - 1,z);
}
if(op == 4){
int x;
x = read();
printf("%lld\n",query(1,1,n,id[x],id[x] + siz[x] - 1));
}
}
return 0;
}
/*
8 10 2 448348
458 718 447 857 633 264 238 944
1 2
2 3
3 4
6 2
1 5
5 7
8 6
3 7 611
4 6
3 1 267
3 2 111
1 6 3 153
3 7 673
4 8
2 6 1
4 7
3 4 228
*/
by qcode_aya @ 2024-08-29 22:18:14
不排除常数过大的原因,#11正常应在5ms内,看了下你的提交记录有5倍时间了。
解决方案:将线段树内左/右儿子及求mid换为位运算。其中开O2下不清楚左/右儿子的部分是否会被优化至位运算,但mid是signed所以是不会被优化的。还有就是左右儿子建议define一下否则可能导致代码变得比较抽象。
其余的等我把测试点下下来到本地测一下再说。
by wuhualin0401 @ 2024-08-29 23:12:44
谢谢,已关