树链剖分小结板子
来源:互联网 发布:淘宝卖家报复的买家 编辑:程序博客网 时间:2024/05/22 04:45
题目链接:树的统计Count
树链剖分(权值在点上)[单点修改 询问区间和/最大值]:
int a[30005];struct node{ int tl,tr,maxx,sum; node():maxx(0),sum(0) {}} tree[120020];void pushup(int id){ tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum; tree[id].maxx=max(tree[id<<1].maxx,tree[id<<1|1].maxx);}void build(int id,int tl,int tr){ tree[id].tl=tl,tree[id].tr=tr; if(tl==tr) { tree[id].maxx=a[tl]; tree[id].sum=a[tl]; } else { int tm=(tl+tr)>>1; build(id<<1,tl,tm); build(id<<1|1,tm+1,tr); pushup(id); }}void update(int id,int wz,int val){ int tl=tree[id].tl,tr=tree[id].tr; if(tl==wz && wz==tr) { tree[id].maxx=val; tree[id].sum=val; } else { int tm=(tl+tr)>>1; if(tm>=wz)update(id<<1,wz,val); else update(id<<1|1,wz,val); pushup(id); }}int get_max(int id,int ql,int qr){ int tl=tree[id].tl,tr=tree[id].tr; if(ql<=tl && tr<=qr)return tree[id].maxx; int tm=(tl+tr)>>1,res1=-inf,res2=-inf; if(tm>=ql)res1=get_max(id<<1,ql,qr); if(tm<qr)res2=get_max(id<<1|1,ql,qr); return max(res1,res2);}int get_sum(int id,int ql,int qr){ int tl=tree[id].tl,tr=tree[id].tr; if(ql<=tl && tr<=qr)return tree[id].sum; int tm=(tl+tr)>>1; int sum=0; if(tm>=ql)sum+=get_sum(id<<1,ql,qr); if(tm<qr)sum+=get_sum(id<<1|1,ql,qr); return sum;}int pre[30005],siz[30005],dep[30005];int top[30005],node_id[30005],heavy[30005];int val[30005],idx=1;vector<int>G[30005];int dfs(int x,int fa,int depth){ dep[x]=depth,pre[x]=fa; int res=1,maxx=0; int len=G[x].size(); for(int i=0; i<len; i++) { if(G[x][i]==fa)continue; int t=dfs(G[x][i],x,depth+1); if(t>maxx)maxx=t,heavy[x]=G[x][i]; res+=t; } return siz[x]=res;}void slpf(int x,int fa,int tp){ node_id[x]=idx++; top[x]=tp; int len=G[x].size(); if(heavy[x])slpf(heavy[x],x,tp); for(int i=0; i<len; i++) { int nex=G[x][i]; if(nex==fa)continue; if(nex!=heavy[x])slpf(nex,x,nex); }}int getmax(int x,int y){ int ans=-inf,res; while(top[x]!=top[y]) { if(dep[top[x]]>dep[top[y]]) { res=get_max(1,node_id[top[x]],node_id[x]); x=pre[top[x]]; } else { res=get_max(1,node_id[top[y]],node_id[y]); y=pre[top[y]]; } if(res>ans)ans=res; } if(dep[x]>dep[y])swap(x,y); res=get_max(1,node_id[x],node_id[y]); if(res>ans)ans=res; return ans;}int getsum(int x,int y){ int ans=0,res; while(top[x]!=top[y]) { if(dep[top[x]]>dep[top[y]]) { res=get_sum(1,node_id[top[x]],node_id[x]); x=pre[top[x]]; } else { res=get_sum(1,node_id[top[y]],node_id[y]); y=pre[top[y]]; } ans+=res; } if(dep[x]>dep[y])swap(x,y); res=get_sum(1,node_id[x],node_id[y]); ans+=res; return ans;}int main(){ int n; scanf("%d",&n); for(int i=1; i<=n-1; i++) { int x,y; scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } dfs(1,0,1); slpf(1,0,1); for(int i=1; i<=n; i++) scanf("%d",&a[node_id[i]]); build(1,1,n); int q; scanf("%d",&q); while(q--) { char op[10]; int x,y; scanf("%s%d%d",op,&x,&y); if(op[0]=='Q' && op[1]=='M') printf("%d\n",getmax(x,y)); if(op[0]=='Q' && op[1]=='S') printf("%d\n",getsum(x,y)); if(op[0]=='C')update(1,node_id[x],y); } return 0;}
题目链接:树上操作
树链剖分(权值在点上)[单点/区间修改 询问区间和]:
struct node{ int tl,tr; ll lazy,sum; node():lazy(0),sum(0) {}}tree[400020];int a[100005];void pushup(int id){ tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;}void build(int id,int tl,int tr){ tree[id].tl=tl,tree[id].tr=tr; tree[id].lazy=tree[id].sum=0; if(tl==tr)tree[id].sum=(ll)a[tl]; else { int tm=(tr+tl)>>1; build(id<<1,tl,tm); build(id<<1|1,tm+1,tr); pushup(id); }}void pushdown(int id){ if(!tree[id].lazy)return; tree[id<<1].lazy+=tree[id].lazy; tree[id<<1|1].lazy+=tree[id].lazy; tree[id<<1].sum+=(tree[id<<1].tr-tree[id<<1].tl+1)*tree[id].lazy; tree[id<<1|1].sum+=(tree[id<<1|1].tr-tree[id<<1|1].tl+1)*tree[id].lazy; tree[id].lazy=0;}void update(int id,int ql,int qr,ll val){ int tl=tree[id].tl,tr=tree[id].tr; if(ql>tr || qr<tl)return; if(ql<=tl && tr<=qr) { tree[id].lazy+=val; tree[id].sum+=(tr-tl+1)*val; return; } pushdown(id); update(id<<1,ql,qr,val); update(id<<1|1,ql,qr,val); pushup(id);}ll get_sum(int id,int ql,int qr){ int tl=tree[id].tl,tr=tree[id].tr; if(ql>tr || qr<tl)return 0; if(ql<=tl && tr<=qr)return tree[id].sum; ll ans=0; pushdown(id); ans+=get_sum(id<<1,ql,qr); ans+=get_sum(id<<1|1,ql,qr); pushup(id); return ans;}int pre[100005],siz[100005],dep[100005];int top[100005],node_id[100005],heavy[100005];int val[100005],lson[100005],rson[100005],idx=0;vector<int>G[100005];int dfs(int x,int fa,int depth){ dep[x]=depth,pre[x]=fa; int res=1,maxx=0; int len=G[x].size(); for(int i=0; i<len; i++) { if(G[x][i]==fa)continue; int t=dfs(G[x][i],x,depth+1); if(t>maxx)maxx=t,heavy[x]=G[x][i]; res+=t; } return siz[x]=res;}void slpf(int x,int fa,int tp){ lson[x]=node_id[x]=++idx; top[x]=tp; int len=G[x].size(); if(heavy[x])slpf(heavy[x],x,tp); for(int i=0; i<len; i++) { int nex=G[x][i]; if(nex==fa)continue; if(nex!=heavy[x])slpf(nex,x,nex); } rson[x]=idx;}ll getsum(int x,int y){ ll ans=0,res; while(top[x]!=top[y]) { if(dep[top[x]]>dep[top[y]]) { res=get_sum(1,node_id[top[x]],node_id[x]); x=pre[top[x]]; } else { res=get_sum(1,node_id[top[y]],node_id[y]); y=pre[top[y]]; } ans+=res; } if(dep[x]>dep[y])swap(x,y); res=get_sum(1,node_id[x],node_id[y]); ans+=res; return ans;}int main(){ int n,q; scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&val[i]); for(int i=1;i<=n-1;i++) { int x,y; scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } dfs(1,0,1); slpf(1,0,1); for(int i=1;i<=n;i++) a[node_id[i]]=val[i]; build(1,1,n); while(q--) { int op,x;ll y; scanf("%d",&op); if(op==1) { scanf("%d%lld",&x,&y); update(1,node_id[x],node_id[x],y); } if(op==2) { scanf("%d%lld",&x,&y); update(1,lson[x],rson[x],y); } if(op==3) { scanf("%d",&x); printf("%lld\n",getsum(1,x)); } } return 0;}
题目链接:Query on a tree
树链剖分(权值在边上)[单点修改 询问区间最大值]:
int a[10005];struct node{ int tl,tr,val;} tree[40020];void pushup(int id){ tree[id].val=max(tree[id<<1].val,tree[id<<1|1].val);}void build(int id,int tl,int tr){ tree[id].tl=tl,tree[id].tr=tr; if(tl==tr)tree[id].val=a[tl]; else { int tm=(tl+tr)>>1; build(id<<1,tl,tm); build(id<<1|1,tm+1,tr); pushup(id); }}void update(int id,int wz,int val){ int tl=tree[id].tl,tr=tree[id].tr; if(tl==wz && wz==tr)tree[id].val=val; else { int tm=(tl+tr)>>1; if(tm>=wz)update(id<<1,wz,val); else update(id<<1|1,wz,val); pushup(id); }}int getval(int id,int ql,int qr){ int tl=tree[id].tl,tr=tree[id].tr; if(ql<=tl && tr<=qr)return tree[id].val; int tm=(tl+tr)>>1,res1=0,res2=0; if(tm>=ql)res1=getval(id<<1,ql,qr); if(tm<qr)res2=getval(id<<1|1,ql,qr); return max(res1,res2);}struct edge{ int nex,id,val; edge(int nex,int id,int val): nex(nex),id(id),val(val) {}};int pre[10005],siz[10005],dep[10005];int top[10005],edge_id[10005],heavy[10005];int val[10005],ith[10005];int idx=1;vector<edge>G[10005];void init(void){ idx=1; memset(a,0,sizeof(a)); memset(ith,0,sizeof(ith)); memset(val,0,sizeof(val)); memset(top,0,sizeof(top)); memset(pre,0,sizeof(pre)); memset(siz,0,sizeof(siz)); memset(dep,0,sizeof(dep)); memset(heavy,0,sizeof(heavy)); memset(tree,0,sizeof(tree)); memset(edge_id,0,sizeof(edge_id));}int dfs(int x,int fa,int depth){ dep[x]=depth,pre[x]=fa; int res=1,maxx=0; int len=G[x].size(); for(int i=0; i<len; i++) { int nex=G[x][i].nex; if(nex==fa)continue; int t=dfs(nex,x,depth+1); ith[G[x][i].id]=nex; val[nex]=G[x][i].val; if(t>maxx) maxx=t,heavy[x]=nex; res+=t; } return siz[x]=res;}void slpf(int x,int fa,int tp){ int len=G[x].size(); if(pre[x])edge_id[x]=idx++; top[x]=tp; if(heavy[x])slpf(heavy[x],x,tp); for(int i=0; i<len; i++) { int nex=G[x][i].nex; if(nex==fa)continue; if(nex!=heavy[x]) slpf(nex,x,nex); }}int getmax(int x,int y){ int ans=0,res; while(top[x]!=top[y]) { if(dep[top[x]]>dep[top[y]]) { res=getval(1,edge_id[top[x]],edge_id[x]); x=pre[top[x]]; } else { res=getval(1,edge_id[top[y]],edge_id[y]); y=pre[top[y]]; } if(res>ans)ans=res; } if(dep[x]<dep[y]) { if(edge_id[heavy[x]]<edge_id[y]) res=getval(1,edge_id[heavy[x]],edge_id[y]); else res=getval(1,edge_id[y],edge_id[heavy[x]]); } if(dep[x]>dep[y]) { if(edge_id[heavy[y]]<edge_id[x]) res=getval(1,edge_id[heavy[y]],edge_id[x]); else res=getval(1,edge_id[x],edge_id[heavy[y]]); } if(res>ans)ans=res; return ans;}int main(){ int T; scanf("%d",&T); while(T--) { init(); int n; scanf("%d",&n); for(int i=1; i<=n-1; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); G[x].push_back(edge(y,i,z)); G[y].push_back(edge(x,i,z)); } dfs(1,0,1); slpf(1,0,1); for(int i=1; i<=n; i++) if(pre[i])a[edge_id[i]]=val[i]; build(1,1,n-1); while(1) { char op[10]; int x,y; scanf("%s",op); if(op[0]=='D')break; scanf("%d%d",&x,&y); if(op[0]=='Q')printf("%d\n",getmax(x,y)); if(op[0]=='C')update(1,edge_id[ith[x]],y); } printf("\n"); for(int i=1; i<=n; i++) G[i].clear(); } return 0;}
题目链接:Aragorn's Story
树链剖分(权值在点上)[区间修改 询问单点值]:
struct node{ int tl,tr,lazy,sum; node():lazy(0),sum(0) {}}tree[200020];int a[50005];void pushup(int id){ tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;}void build(int id,int tl,int tr){ tree[id].tl=tl,tree[id].tr=tr; tree[id].lazy=tree[id].sum=0; if(tl==tr)tree[id].sum=a[tl]; else { int tm=(tr+tl)>>1; build(id<<1,tl,tm); build(id<<1|1,tm+1,tr); pushup(id); }}void pushdown(int id){ if(!tree[id].lazy)return; tree[id<<1].lazy+=tree[id].lazy; tree[id<<1|1].lazy+=tree[id].lazy; tree[id<<1].sum+=(tree[id<<1].tr-tree[id<<1].tl+1)*tree[id].lazy; tree[id<<1|1].sum+=(tree[id<<1|1].tr-tree[id<<1|1].tl+1)*tree[id].lazy; tree[id].lazy=0;}void update(int id,int ql,int qr,int val){ int tl=tree[id].tl,tr=tree[id].tr; if(ql>tr || qr<tl)return; if(ql<=tl && tr<=qr) { tree[id].lazy+=val; tree[id].sum+=(tr-tl+1)*val; return; } pushdown(id); update(id<<1,ql,qr,val); update(id<<1|1,ql,qr,val); pushup(id);}int get_sum(int id,int ql,int qr){ int tl=tree[id].tl,tr=tree[id].tr; if(ql>tr || qr<tl)return 0; if(ql<=tl && tr<=qr)return tree[id].sum; int ans=0; pushdown(id); ans+=get_sum(id<<1,ql,qr); ans+=get_sum(id<<1|1,ql,qr); pushup(id); return ans;}int pre[50005],siz[50005],dep[50005];int top[50005],node_id[50005],heavy[50005];int val[50005],idx=0;vector<int>G[50005];int dfs(int x,int fa,int depth){ dep[x]=depth,pre[x]=fa; int res=1,maxx=0; int len=G[x].size(); for(int i=0; i<len; i++) { if(G[x][i]==fa)continue; int t=dfs(G[x][i],x,depth+1); if(t>maxx)maxx=t,heavy[x]=G[x][i]; res+=t; } return siz[x]=res;}void slpf(int x,int fa,int tp){ node_id[x]=++idx,top[x]=tp; int len=G[x].size(); if(heavy[x])slpf(heavy[x],x,tp); for(int i=0; i<len; i++) { int nex=G[x][i]; if(nex==fa)continue; if(nex!=heavy[x])slpf(nex,x,nex); }}void change(int x,int y,int z){ while(top[x]!=top[y]) { if(dep[top[x]]>dep[top[y]]) { update(1,node_id[top[x]],node_id[x],z); x=pre[top[x]]; } else { update(1,node_id[top[y]],node_id[y],z); y=pre[top[y]]; } } if(dep[x]>dep[y])swap(x,y); update(1,node_id[x],node_id[y],z);}void init(void){ idx=0; memset(a,0,sizeof(a)); memset(val,0,sizeof(val)); memset(top,0,sizeof(top)); memset(pre,0,sizeof(pre)); memset(siz,0,sizeof(siz)); memset(dep,0,sizeof(dep)); memset(heavy,0,sizeof(heavy)); memset(tree,0,sizeof(tree)); memset(node_id,0,sizeof(node_id));}int main(){ int n,m,q; while(~scanf("%d%d%d",&n,&m,&q)) { init(); for(int i=1;i<=n;i++) scanf("%d",&val[i]); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } dfs(1,0,1); slpf(1,0,1); for(int i=1;i<=n;i++) a[node_id[i]]=val[i]; build(1,1,n); while(q--) { char op[2];int x,y,z; scanf("%s",op); if(op[0]=='I') { scanf("%d%d%d",&x,&y,&z); change(x,y,z); } if(op[0]=='D') { scanf("%d%d%d",&x,&y,&z); change(x,y,-z); } if(op[0]=='Q') { scanf("%d",&x); printf("%d\n",get_sum(1,node_id[x],node_id[x])); } } for(int i=1;i<=n;i++)G[i].clear(); } return 0;}
题目链接:软件包管理器
树链剖分(权值在点上)[区间修改 询问区间和]:
struct node{ int tl,tr,lazy,sum; node():lazy(-1),sum(0) {}}tree[400020];inline void pushup(int id){ tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;}void build(int id,int tl,int tr){ tree[id].tl=tl,tree[id].tr=tr; if(tl==tr)tree[id].lazy=-1; else { int tm=(tr+tl)>>1; build(id<<1,tl,tm); build(id<<1|1,tm+1,tr); pushup(id); }}void pushdown(int id){ if(tree[id].lazy==-1)return; tree[id<<1].lazy=tree[id].lazy; tree[id<<1|1].lazy=tree[id].lazy; tree[id<<1].sum=(tree[id<<1].tr-tree[id<<1].tl+1)*tree[id].lazy; tree[id<<1|1].sum=(tree[id<<1|1].tr-tree[id<<1|1].tl+1)*tree[id].lazy; tree[id].lazy=-1;}void update(int id,int ql,int qr,int val){ int tl=tree[id].tl,tr=tree[id].tr; if(ql>tr || qr<tl)return; if(ql<=tl && tr<=qr) { tree[id].lazy=val; tree[id].sum=(tr-tl+1)*val; return; } pushdown(id); update(id<<1,ql,qr,val); update(id<<1|1,ql,qr,val); pushup(id);}int get_sum(int id,int ql,int qr){ int tl=tree[id].tl,tr=tree[id].tr; if(ql>tr || qr<tl)return 0; if(ql<=tl && tr<=qr)return tree[id].sum; int ans=0; pushdown(id); ans+=get_sum(id<<1,ql,qr); ans+=get_sum(id<<1|1,ql,qr); pushup(id); return ans;}int uninall(int id,int ql,int qr){ int tl=tree[id].tl,tr=tree[id].tr; if(ql>tr || qr<tl)return 0; if(ql<=tl && tr<=qr) { int ans=tree[id].sum; tree[id].lazy=0; tree[id].sum=0; return ans; } int ans=0; pushdown(id); ans+=uninall(id<<1,ql,qr); ans+=uninall(id<<1|1,ql,qr); pushup(id); return ans;}int pre[100005],siz[100005],dep[100005];int top[100005],node_id[100005],heavy[100005];int lson[100005],rson[100005],idx=0;struct{ int nex,nex_node;} edge[100005];int head[100005],cont=0;void add_edge(int now,int nex){ edge[cont].nex=nex; edge[cont].nex_node=head[now]; head[now]=cont++;}int dfs(int x,int fa,int depth){ dep[x]=depth,pre[x]=fa; int res=1,maxx=0; for(int i=head[x];~i;i=edge[i].nex_node) { int nex=edge[i].nex; if(nex==fa)continue; int t=dfs(nex,x,depth+1); if(t>maxx)maxx=t,heavy[x]=nex; res+=t; } return siz[x]=res;}void slpf(int x,int fa,int tp){ lson[x]=node_id[x]=++idx; top[x]=tp; if(heavy[x])slpf(heavy[x],x,tp); for(int i=head[x];~i;i=edge[i].nex_node) { int nex=edge[i].nex; if(nex==fa)continue; if(nex!=heavy[x])slpf(nex,x,nex); } rson[x]=idx;}int getsum(int x,int y,int z){ int ans=0,res; while(top[x]!=top[y]) { if(dep[top[x]]>dep[top[y]]) { res=get_sum(1,node_id[top[x]],node_id[x]); update(1,node_id[top[x]],node_id[x],z); x=pre[top[x]]; } else { res=get_sum(1,node_id[top[y]],node_id[y]); update(1,node_id[top[y]],node_id[y],z); y=pre[top[y]]; } ans+=res; } if(dep[x]>dep[y])swap(x,y); res=get_sum(1,node_id[x],node_id[y]); update(1,node_id[x],node_id[y],z); ans+=res; return ans;}int main(){ memset(head,-1,sizeof(head)); int n,t; scanf("%d",&n); for(int i=2;i<=n;i++) { scanf("%d",&t); add_edge(t+1,i); } dfs(1,0,1); slpf(1,0,1); build(1,1,n); int q; scanf("%d",&q); while(q--) { char op[15];int x; scanf("%s%d",op,&x); if(op[0]=='i') { int res=getsum(x+1,1,1); printf("%d\n",dep[x+1]-res); } else { int res=uninall(1,lson[x+1],rson[x+1]); printf("%d\n",res); } } return 0;}
作者:fo0Old
链接:http://www.jianshu.com/p/03f365028725
來源:简书
阅读全文
0 0
- 树链剖分小结板子
- DM6437板子小结
- 【板子】树链剖分
- adb 连接 板子 报错 小结
- 【CODEVS】树链剖分板子
- 板子
- 板子
- 测试板子
- 板子总结
- 入手板子
- 新板子
- Ivus 板子
- dinic 板子
- manacher板子
- 左偏树 板子
- NTT板子
- RMQ板子
- spfa板子
- HDU6053 TrickGCD(2017多校第2场)
- linux安装jdk mysql tomcat之部署项目
- 图像处理基本概念(模板,卷积运算)
- 原型和作用域
- <Android 基础(三十七)> 自定义ViewPagerIndicator
- 树链剖分小结板子
- iDesktop点数据集构建DEM时三种插值方式的选择
- 深度学习笔记---规范化
- fairyguiUI适配问题
- 自定义文件系统类加载器
- Centos 7.3 Install Mysql+keepalived 高可用
- “新消费时代” 来了——携手众智云,做消费商 “新消费,您做主”!
- mysql导入数据时 USING BTREE 错误解决办法(存在索引)
- 前端性能优化之——缓存