Luogu 3384(树链剖分)

来源:互联网 发布:我在回忆里等你 知乎 编辑:程序博客网 时间:2024/05/27 21:50

传送门

模板题,其中线段树部分也可以使用树状数组实现(区间操作略显麻烦)。

#include<bits/stdc++.h>using namespace std;#define lson rt<<1,l,mid#define rson rt<<1|1,mid+1,r#define root 1,1,ntypedef long long ll;const int MAXN=1e5+4;int rot,n,m,a[MAXN];vector<int > g[MAXN];int fa[MAXN],dep[MAXN],siz[MAXN],son[MAXN],top[MAXN],in[MAXN],out[MAXN],rk[MAXN],tim=0;/*------------DCP------------*/void dfs1(int p,int father,int d) {siz[p]=1,dep[p]=d,fa[p]=father;for (int i=0;i<g[p].size();++i) {int v=g[p][i];if (v^father) {dfs1(v,p,d+1);siz[p]+=siz[v];if (son[p]==-1||siz[v]>siz[son[p]])son[p]=v;}}}void dfs2(int p,int tp) {top[p]=tp,in[p]=++tim,rk[tim]=p;if (~son[p]) dfs2(son[p],tp);for (int i=0;i<g[p].size();++i) {int v=g[p][i];if (v^fa[p]&&v^son[p])dfs2(v,v);}out[p]=tim;}/*------------Segment Tree------------*/ll sum[MAXN<<2],laz[MAXN<<2],mod;void build(int rt,int l,int r) {laz[rt]=0;if (l==r) {sum[rt]=a[rk[l]];return ;}int mid=l+r>>1;build(lson);build(rson);(sum[rt]=sum[rt<<1]+sum[rt<<1|1])%=mod;}inline void pushdown(int rt,int len) {if (laz[rt]) {(laz[rt<<1]+=laz[rt])%=mod;(laz[rt<<1|1]+=laz[rt])%=mod;(sum[rt<<1]+=laz[rt]*(len-(len>>1)))%=mod;(sum[rt<<1|1]+=laz[rt]*(len>>1))%=mod;laz[rt]=0;}}void modify(int rt,int l,int r,int L,int R,ll val) {if (L<=l&&r<=R) {(sum[rt]+=val*(r-l+1))%=mod;(laz[rt]+=val)%=mod;return ;}pushdown(rt,r-l+1);int mid=l+r>>1;if (L<=mid) modify(lson,L,R,val);if (mid<R) modify(rson,L,R,val);(sum[rt]=sum[rt<<1]+sum[rt<<1|1])%=mod;}ll query(int rt,int l,int r,int L,int R) {if (L<=l&&r<=R) return sum[rt];pushdown(rt,r-l+1);int mid=l+r>>1;ll ret=0;if (L<=mid) (ret+=query(lson,L,R))%=mod;if (mid<R) (ret+=query(rson,L,R))%=mod;return ret;}ll ask(int x,int y) {ll ret=0;while (top[x]^top[y]) {if (dep[top[x]]<dep[top[y]]) x^=y^=x^=y;(ret+=query(root,in[top[x]],in[x]))%=mod;x=fa[top[x]];}if (dep[x]<dep[y]) x^=y^=x^=y;(ret+=query(root,in[y],in[x]))%=mod;return ret;}void change(int x,int y,ll v) {while (top[x]^top[y]) {if (dep[top[x]]<dep[top[y]]) x^=y^=x^=y;modify(root,in[top[x]],in[x],v);x=fa[top[x]];}if (dep[x]<dep[y]) x^=y^=x^=y;modify(root,in[y],in[x],v);}inline int read() {int x=0,f=1;char c=getchar();while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();return x*f;}int main() {//freopen("P3384.in","r",stdin);memset(son,-1,sizeof(son));n=read(),m=read(),rot=read(),mod=read();for (register int i=1;i<=n;++i) a[i]=read()%mod,g[i].clear();for (register int i=1;i<n;++i) {int u=read(),v=read();g[u].push_back(v);g[v].push_back(u);}dfs1(rot,0,1);dfs2(rot,rot);build(root);for (register int i=0;i<m;++i) {int opt=read();switch (opt) {case 1:{int x=read(),y=read();ll v=read();change(x,y,v);break;}case 2:{int x=read(),y=read();printf("%lld\n",ask(x,y));break;}case 3:{int x=read();ll v=read();modify(root,in[x],out[x],v);break;}case 4:{int x=read();printf("%lld\n",query(root,in[x],out[x]));break;}}}return 0;}


原创粉丝点击