傻逼调了一天树剖
Posted orzzz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了傻逼调了一天树剖相关的知识,希望对你有一定的参考价值。
啊,,调了很久就是了。
跳链的时候跳的是top的深度大的那个,不是本身深度大的。
我是傻逼。
洛谷树剖模板。
#include<bits/stdc++.h> using namespace std; const int N=100010; typedef long long ll; inline ll read(){ ll f=1,r=0,c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){r=r*10+c-‘0‘;c=getchar();} return r*f; } struct Edge{ int to,nxt; }e[N*2]; int head[N],cnt=1;ll P; void add(int u,int v){ e[cnt]=(Edge){v,head[u]}; head[u]=cnt++; e[cnt]=(Edge){u,head[v]}; head[v]=cnt++; } int siz[N],dep[N],dad[N],son[N]; void dfs1(int u,int fa){ siz[u]=1;dad[u]=fa; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(v==fa)continue; dep[v]=dep[u]+1;dfs1(v,u); siz[u]+=siz[v]; if(siz[v]>siz[son[u]]) son[u]=v; } } int pos[N],top[N],dfn; void dfs2(int u,int anc){ top[u]=anc;pos[u]=++dfn; if(!son[u])return; dfs2(son[u],anc); for(int i=head[u];i;i=e[i].nxt) if(e[i].to^dad[u]&&e[i].to^son[u]) dfs2(e[i].to,e[i].to); } #define ls o<<1 #define rs (o<<1)|1 #define L T[o].l #define R T[o].r #define M L+R>>1 struct Node{ ll l,r,add,sum; }T[N*4]; ll a[N],b[N]; void pushdown(int o){ (T[ls].add+=T[o].add)%=P; (T[rs].add+=T[o].add)%=P; (T[ls].sum+=(T[ls].r-T[ls].l+1)*T[o].add)%=P; (T[rs].sum+=(T[rs].r-T[rs].l+1)*T[o].add)%=P; T[o].add=0; } void pullup(int o){ (T[o].sum=T[ls].sum+T[rs].sum)%=P; } void build(int o,int l,int r){ if(l==r){ T[o]=(Node){l,r,0,a[l]}; return; } T[o]=(Node){l,r,0,0}; build(ls,l,l+r>>1); build(rs,(l+r>>1)+1,r); pullup(o); } ll val,ans,ql,qr; void upd(int o){ if(ql<=L&&R<=qr){ (T[o].add+=val)%=P; (T[o].sum+=(R-L+1)*val)%=P; return; } pushdown(o); if(ql<=M)upd(ls); if(qr>M) upd(rs); pullup(o); } void qsum(int o){ if(ql<=L&&R<=qr){ (ans+=T[o].sum)%=P; return; } pushdown(o); if(ql<=M)qsum(ls); if(qr>M) qsum(rs); } void modify(int u,int v,ll t){ val=t; while(top[u]^top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); ql=pos[top[u]],qr=pos[u];upd(1); u=dad[top[u]]; } if(pos[u]>pos[v])swap(u,v); ql=pos[u],qr=pos[v];upd(1); } void query(int u,int v){ ans=0; while(top[u]^top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); ql=pos[top[u]],qr=pos[u];qsum(1); u=dad[top[u]]; } if(pos[u]>pos[v])swap(u,v); ql=pos[u],qr=pos[v];qsum(1); printf("%lld\n",ans%P); } int n,m,S; void init(){ n=read(),m=read(),S=read(),P=read(); for(int i=1;i<=n;i++)b[i]=read(); for(int i=1;i<n;i++) add(read(),read()); dfs1(S,0);dfs2(S,S); for(int i=1;i<=n;i++) a[pos[i]]=b[i]; build(1,1,n); } void solve(){ while(m--){ int opt=read(); if(opt==1){ int u=read(),v=read();ll t=read(); modify(u,v,t); } else if(opt==2){ int u=read(),v=read(); query(u,v); } else if(opt==3){ int u=read(); ql=pos[u],qr=ql+siz[u]-1; val=read();upd(1); } else{ int u=read(); ans=0; ql=pos[u],qr=ql+siz[u]-1; qsum(1); printf("%lld\n",ans%P); } } } int main(){ init(); solve(); }
感觉150行,3KB左右,字数算不多了,打了几遍也基本记下来了。
以上是关于傻逼调了一天树剖的主要内容,如果未能解决你的问题,请参考以下文章