呵呵
来源:互联网 发布:数据字典模板 编辑:程序博客网 时间:2024/05/16 17:22
题目:
https://www.luogu.org/problemnew/show/3384#sub
WA的原因:
change时忘记push操作;
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;const ll MAXN=1000001;ll son[MAXN],siz[MAXN],fa[MAXN],nxt[MAXN],fst[MAXN];ll deep[MAXN],top[MAXN],inseg[MAXN],intr[MAXN],num[MAXN];ll tot,totp,n,m,r,p;struct Tree {ll l,r,sum,delta;}tree[MAXN];struct hh {ll from,to;}ma[MAXN];void build(ll f,ll t) {ma[++tot]=(hh){f,t},nxt[tot]=fst[f],fst[f]=tot;}void up(ll now) {tree[now].sum=(tree[now<<1].sum+tree[now<<1|1].sum)%p;}void dfs1(ll x,ll f){ fa[x]=f,deep[x]=deep[f]+1,siz[x]=1; for(ll i=fst[x];i;i=nxt[i]) { ll v=ma[i].to; if(v==f) continue; dfs1(v,x),siz[x]+=siz[v]; if(!son[x] || siz[son[x]]<siz[v]) son[x]=v; } return;}void dfs2(ll x,ll st){ top[x]=st,inseg[x]=++totp,intr[totp]=x; if(!son[x]) return; dfs2(son[x],st); for(ll i=fst[x];i;i=nxt[i]) { ll v=ma[i].to; if(v==fa[x] || v==son[x]) continue; dfs2(v,v); } return;}void push(ll now){ if(tree[now].delta) { tree[now<<1].sum=(tree[now<<1].sum+(tree[now<<1].r-tree[now<<1].l+1)*tree[now].delta)%p; tree[now<<1].delta=tree[now<<1].delta+tree[now].delta; tree[now<<1|1].sum=(tree[now<<1|1].sum+(tree[now<<1|1].r-tree[now<<1|1].l+1)*tree[now].delta)%p; tree[now<<1|1].delta=tree[now<<1|1].delta+tree[now].delta; tree[now].delta=0; } return;}void build_tree(ll now,ll l,ll r){ ll mid=(l+r)>>1; tree[now].l=l,tree[now].r=r,tree[now].delta=0; if(l==r) { tree[now].sum=num[intr[l]];return;} build_tree(now<<1,l,mid),build_tree(now<<1|1,mid+1,r); up(now);return;}void change_sum(ll now,ll l,ll r,ll v){ ll mid=(tree[now].l+tree[now].r)>>1; if(tree[now].l>=l && tree[now].r<=r) {tree[now].sum=((tree[now].r-tree[now].l+1)*v+tree[now].sum)%p; tree[now].delta=tree[now].delta+v;return;} push(now); if(l<=mid) change_sum(now<<1,l,r,v); if(r>=mid+1) change_sum(now<<1|1,l,r,v); up(now);return;}ll query_sum(ll now,ll l,ll r){ ll ans=0; if(tree[now].l>=l && tree[now].r<=r) return tree[now].sum; push(now); int mid=(tree[now].l+tree[now].r)>>1; if(l<=mid) ans=ans+query_sum(now<<1,l,r); if(r>=mid+1) ans=ans+query_sum(now<<1|1,l,r); return ans%p;}void change_tree(ll x,ll y,ll z){ ll fx=top[x],fy=top[y]; while(fx!=fy) { if(deep[fx]<deep[fy]) swap(fx,fy),swap(x,y); change_sum(1,inseg[fx],inseg[x],z),x=fa[fx],fx=top[x]; } if(deep[x]>deep[y]) swap(x,y); change_sum(1,inseg[x],inseg[y],z); return;}ll query_tree(ll x,ll y){ ll ans=0,fx=top[x],fy=top[y]; while(fx!=fy) { if(deep[fx]<deep[fy]) swap(fx,fy),swap(x,y); ans=(ans+query_sum(1,inseg[fx],inseg[x]))%p,x=fa[fx],fx=top[x]; } if(deep[x]>deep[y]) swap(x,y); ans=(ans+query_sum(1,inseg[x],inseg[y]))%p; return ans%p;}void solve(){ ll opt,x,y,z; scanf("%lld%lld%lld%lld",&n,&m,&r,&p); for(int i=1;i<=n;i++) scanf("%lld",&num[i]); for(int i=1;i<n;i++) scanf("%lld%lld",&x,&y),build(x,y),build(y,x); dfs1(r,0),dfs2(r,r),build_tree(1,1,n); for(int i=1;i<=m;i++) { scanf("%lld%lld",&opt,&x); if(opt==1) scanf("%lld%lld",&y,&z),change_tree(x,y,z); else if(opt==2) scanf("%lld",&y),printf("%lld\n",query_tree(x,y)%p); else if(opt==3) scanf("%lld",&z),change_sum(1,inseg[x],inseg[x]+siz[x]-1,z); else if(opt==4) printf("%lld\n",query_sum(1,inseg[x],inseg[x]+siz[x]-1)%p); } return;}int main(){ solve(); return 0;}