【P3384】【模板】树链剖分
来源:互联网 发布:布拉德利比尔数据 编辑:程序博客网 时间:2024/06/05 21:57
树链剖分就是将树上的点通过轻重链剖分来将其合理地(即时间复杂度令人满意)hash成一个线段,之后再用线段树来维护。
也可以想象成将树上最长的链拿出来,短的链就在旁边填填补补这种感觉?
详细讲的话,像我这种蒟蒻肯定是讲不好的,各种分析也不会,丢个代码直接细软跑好了。
hashh是正向hash。
hashv是反向hash,致敬韦神。
#include<bits/stdc++.h>#define fer(i,j,n) for(int i=j;i<=n;i++)#define far(i,j,n) for(int i=j;i>=n;i--)#define ll long long#define pa pair<int,int>const int maxn=500010;const int INF=1e9+7;using namespace std;/*----------------------------------------------------------------------------*/inline ll read(){ char ls;ll x=0,sng=1; for(;ls<'0'||ls>'9';ls=getchar())if(ls=='-')sng=-1; for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0'; return x*sng;}/*----------------------------------------------------------------------------*/ll n,m,root,mod; struct kaga{ int next; int point;}e[maxn];struct akagi{ int l,r; ll sum,lazy;}tr[maxn];int last[maxn],k=0,fa[maxn],size[maxn],son[maxn],belong[maxn],hashh[maxn],hashv[maxn],dep[maxn],v[maxn];void sumup(int x){ tr[x].sum=(tr[x<<1].sum+tr[x<<1|1].sum)%mod; return ;}void pushdown(int x){ int y=tr[x].lazy; if(y) { tr[x<<1].lazy+=y; tr[x<<1].sum+=(tr[x<<1].r-tr[x<<1].l+1)*y; tr[x<<1|1].lazy+=y; tr[x<<1|1].sum+=(tr[x<<1|1].r-tr[x<<1|1].l+1)*y; tr[x].lazy=0; } return ;}void build(int x,int l,int r){ int mid=(l+r)>>1; tr[x].l=l;tr[x].r=r; if(l==r) { tr[x].sum=v[hashv[l]]; tr[x].lazy=0; return ; } build(x<<1,l,mid); build(x<<1|1,mid+1,r); sumup(x); return ;}void change(int x,int L,int R,int val){ int l=tr[x].l,r=tr[x].r,mid=(l+r)>>1; if(L<=l&&r<=R) { tr[x].lazy+=val;tr[x].lazy%=mod; tr[x].sum+=val*(r-l+1);tr[x].sum%=mod; return ; } pushdown(x); if(R<=mid)change(x<<1,L,R,val); else if(L>mid)change(x<<1|1,L,R,val); else change(x<<1,L,mid,val),change(x<<1|1,mid+1,R,val); sumup(x); return ;}ll query(int x,int L,int R){ int l=tr[x].l,r=tr[x].r,mid=(l+r)>>1; if(L<=l&&r<=R)return tr[x].sum; pushdown(x); if(R<=mid)query(x<<1,L,R); else if(L>mid)query(x<<1|1,L,R); else return (query(x<<1,L,mid)+query(x<<1|1,mid+1,R))%mod;}void add_edge(int x,int y){ e[++k].next=y;e[k].point=last[x];last[x]=k;}void insert(int x,int y){ add_edge(x,y); add_edge(y,x);}void dfs1(int x,int fat){ fa[x]=fat; dep[x]=dep[fat]+1; size[x]=1; for(int j=last[x];j;j=e[j].point) { int y=e[j].next; if(y==fat)continue; dfs1(y,x); size[x]+=size[y]; if(!son[x]||size[y]>size[son[x]]) son[x]=y; }}void dfs2(int x,int top){ belong[x]=top; hashh[x]=++k; hashv[k]=x; if(!son[x])return ; dfs2(son[x],top); for(int j=last[x];j;j=e[j].point) { int y=e[j].next; if(y!=son[x]&&y!=fa[x]) dfs2(y,y); }}void update(int x,int y,int val){ int topx=belong[x]; int topy=belong[y]; while(topx!=topy) { if(dep[topx]<dep[topy]) { swap(x,y); swap(topx,topy); } change(1,hashh[topx],hashh[x],val); x=fa[topx]; topx=belong[x]; } if(dep[x]>dep[y])swap(x,y); change(1,hashh[x],hashh[y],val);}ll sigma(int x,int y){ ll sum=0; int topx=belong[x]; int topy=belong[y]; while(topx!=topy) { if(dep[topx]<dep[topy]) { swap(x,y); swap(topx,topy); } sum+=query(1,hashh[topx],hashh[x]); sum%=mod; x=fa[topx]; topx=belong[x]; } if(dep[x]>dep[y])swap(x,y); sum+=query(1,hashh[x],hashh[y]); return sum%mod;}void updateson(int x,int val){ int left=hashh[x]; int right=hashh[x]+size[x]-1; change(1,left,right,val);}ll sigmason(int x){ int left=hashh[x]; int right=hashh[x]+size[x]-1; return query(1,left,right)%mod;}int main(){ n=read();m=read();root=read();mod=read(); fer(i,1,n)v[i]=read(); fer(i,1,n-1) { int x=read(),y=read(); insert(x,y); } k=0; dfs1(root,0); dfs2(root,root); build(1,1,n); fer(i,1,m) { int opt=read(); if(opt==1) { int x=read(),y=read(),z=read(); update(x,y,z); } else if(opt==2) { int x=read(),y=read(); cout<<sigma(x,y)<<endl; } else if(opt==3) { int x=read(),y=read(); updateson(x,y); } else { int x=read(); cout<<sigmason(x)<<endl; } }}
阅读全文
0 0
- 洛谷 P3384 【模板】树链剖分
- P3384 【模板】树链剖分
- 洛谷 P3384 【模板】树链剖分
- 洛谷 P3384 【模板】树链剖分
- 【洛谷P3384】【模板】树链剖分
- 洛谷 P3384 【模板】树链剖分
- 【P3384】【模板】树链剖分
- 树链剖分 模板 洛谷p3384
- P3384 【模板】树链剖分
- 树链剖分 模板 洛谷P3384
- 洛谷P3384 【模板】树链剖分
- 洛谷P3384【模板】树链剖分
- 洛谷P3384【模板】树链剖分 (树链剖分)
- 洛谷 P3384 【模板】树链剖分(指针版)
- 树链剖分模板——Luogu P3384
- 树链剖分 洛谷p3384
- 树链剖分 模板
- 模板-树链剖分
- lua.c:80:31: fatal error: readline/readline.h: No such file or directory
- 字体使用sp、dp的区别
- 微信公众号开发之获取用户基本信息
- 支持向量机(SVM)
- OneNet学习笔记(二)——OneNet平台初识
- 【P3384】【模板】树链剖分
- C#之11 字符串的不可变性 -----值类型与引用类型
- 秒杀99%的面试题
- java发送http的get、post请求
- TypeScript变量声明
- linux下搭建lua开发环境
- APP接口安全设计
- PHP 数据类型
- python入门系列14―——随机数