目前70pts,剩三个大数据点没过,对着数据点2的数据调了半天的取模,还是错的
目前我也不清楚是哪里的问题,暂时没看出树剖和线段树的逻辑问题,所以我暂且认为是取模的问题。
求帮忙看看,我自己同时也会找
谢谢,orz
#define fileopen freopen("in","r",stdin);cout << "freopen here" << endl
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 1e5 + 10;
int n,m,r,MOD;
int son[maxn],vis[maxn],siz[maxn],depth[maxn],f[maxn];
int top[maxn],dfn[maxn],rdfn[maxn],val[maxn];
int sum[maxn << 2],lz[maxn << 2];
int fst[maxn],nxt[maxn << 1];
struct edge{
int u,v;
}side[maxn << 1];
int tnt,cnt;
void dfs1(int u) {
son[u] = -1;
siz[u] += 1;
for(int i = fst[u]; i; i = nxt[i]) {
int v = side[i].v;
if(!depth[v]) {
depth[v] = depth[u] + 1;
f[v] = u;
dfs1(v);
siz[u] += siz[v];
if(son[u] == -1 || siz[son[u]] < siz[v])
son[u] = v;
}
}
}
void dfs2(int u,int t) {
top[u] = t;
dfn[u] = ++tnt;
rdfn[tnt] = u;
if(son[u] == -1)
return ;
dfs2(son[u],t);
for(int i = fst[u]; i; i = nxt[i]) {
int v = side[i].v;
if(son[u] != v && v != f[u])
dfs2(v,v);
}
}
void add(int u,int v) {
side[++cnt] = {u,v};
nxt[cnt] = fst[u];
fst[u] = cnt;
}
void build(int rt,int l,int r) {
if(l == r) {
sum[rt] = (sum[rt] + val[rdfn[l]]) % MOD;
return ;
}
int m = l + r >> 1;
build(rt << 1,l,m);
build(rt << 1 | 1,m + 1,r);
sum[rt] = (sum[rt << 1] + sum[rt << 1 | 1]) % MOD;
}
void pushdown(int rt,int l,int r) {
if(lz[rt] == 0)
return ;
lz[rt] %= MOD;
int m = l + r >> 1;
lz[rt << 1] += lz[rt];
lz[rt << 1] %= MOD;
lz[rt << 1 | 1] += lz[rt];
lz[rt << 1 | 1] %= MOD;
sum[rt << 1] = ((sum[rt << 1] + 1ll * lz[rt] * (m - l + 1) % MOD) % MOD + MOD) % MOD;
sum[rt << 1 | 1] = ((sum[rt << 1 | 1] + 1ll * lz[rt] * (r - m - 1 + 1) % MOD) + MOD) % MOD;
lz[rt] = 0;
}
void update(int rt,int l,int r,int x,int y,int k) {
pushdown(rt,l,r);
if(x <= l && r <= y) {
k %= MOD;
lz[rt] += k;lz[rt] %= MOD;
sum[rt] = (sum[rt] + 1ll * k * (r - l + 1) % MOD) % MOD;
return ;
}
int m = l + r >> 1;
if(x <= m) update(rt << 1,l,m,x,y,k);
if(y > m) update(rt << 1 | 1,m + 1,r,x,y,k); //here fuck
sum[rt] = ((sum[rt << 1] % MOD + sum[rt << 1 | 1] % MOD) + 2ll * MOD) % MOD;
}
void upd_chain(int x,int y,int k) {
k %= MOD;
while(top[x] != top[y]) {
if(depth[top[x]] < depth[top[y]])
swap(x,y);
update(1,1,n,dfn[top[x]],dfn[x],k);
x = f[top[x]];
}
if(depth[x] < depth[y])
swap(x,y);
update(1,1,n,dfn[y],dfn[x],k); // here
}
int query(int rt,int l,int r,int x,int y) {
pushdown(rt,l,r);
if(x <= l && r <= y) {
return sum[rt] % MOD;
}
int m = l + r >> 1;
ll ret = 0;
if(x <= m) ret += query(rt << 1,l,m,x,y) % MOD;
if(y > m) ret += query(rt << 1 | 1,m + 1,r,x,y) % MOD;
return ret % MOD;
}
int query_chain(int x,int y) {
ll ret = 0;
while(top[x] != top[y]) {
if(depth[top[x]] < depth[top[y]])
swap(x,y);
ret += query(1,1,n,dfn[top[x]],dfn[x]) % MOD;
ret %= MOD;
x = f[top[x]];
}
if(depth[x] < depth[y])
swap(x,y);
ret += query(1,1,n,dfn[y],dfn[x]) % MOD;
return ret % MOD;
}
int main() {
fileopen;
freopen("my_ans","w",stdout);
cin >> n >> m >> r >> MOD;
for(int i = 1; i <= n; ++i)
scanf("%d",val + i);
for(int i = 0; i < n - 1; ++i) {
int u,v;
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
for(int i = 1; i <= n; ++i)
f[i] = i;
depth[r] = 1;
dfs1(r);
dfs2(r,r);
build(1,1,n);
int flag,a,b,c;
for(int i = 0; i < m; ++i) {
scanf("%d",&flag);
if(flag == 1) {
scanf("%d%d%d",&a,&b,&c);
upd_chain(a,b,c);
} else if(flag == 4) {
scanf("%d",&a);
printf("%d\n",(query(1,1,n,dfn[a],dfn[a] + siz[a] - 1) % MOD + MOD) % MOD);
} else {
scanf("%d%d",&a,&b);
if(flag == 2) {
printf("%d\n",query_chain(a,b));
} else {
update(1,1,n,dfn[a],dfn[a] + siz[a] - 1,b);
}
}
}
return 0;
}