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;}
阅读全文
0 0
- Luogu 3384(树链剖分)
- Luogu 3384 树链剖分+线段树
- Luogu 1280(dp)
- Luogu 1282(dp)
- Luogu 1387(dp)
- Luogu 2661(tarjan)
- Luogu 2330(kruskal)
- Luogu 1156(dp)
- Luogu 1186(SPFA)
- Luogu 1141(dp)
- Luogu 3378(堆)
- Luogu 3370(hash)
- Luogu 3379(LCA)
- Luogu 3375(KMP)
- Luogu 3382(三分)
- Luogu 3805(manacher)
- Luogu 1880(区间dp)
- Luogu 3368(树状数组)
- 杭电oj2087
- 概述 《计算机网络第六版》谢希仁
- 策略模式接口和抽象类的简单实现
- 机器学习实战-7AdaBoost提升算法
- 图片懒加载及资源节流
- Luogu 3384(树链剖分)
- Python和和其他语言的对比
- 如何验证成为微信开发者
- easyui 防止页面加载出现dialog等其他非主页信息
- const的指针和引用
- 输入任意一个整数,编程判断这个数的奇偶性。
- MVP模式实现网络请求数据并添加到列表(Rxjava+Retrofit)
- javascript之杂七杂八
- ex2_6 排列