bzoj1036 [ZJOI2008]树的统计(树链剖分)
来源:互联网 发布:西安首届程序员节 编辑:程序博客网 时间:2024/05/21 01:56
树链剖分就是划分轻重链,把每个点映射到线段树上,保证一条重链上的点在线段树中是一段完整的区间。可以由2遍dfs完成。主要还是个线段树。复杂度
#include <bits/stdc++.h>using namespace std;#define ll long long#define inf 0x3f3f3f3f#define N 30010inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f;}int n,a[N],h[N],num=0,fa[N],dep[N],son[N],size[N],top[N],id[N],dfn=0;struct edge{ int to,next;}data[N<<1];struct node{ int mx,sum;}tree[N<<2];void dfs1(int x){ size[x]=1; for(int i=h[x];i;i=data[i].next){ int y=data[i].to; if(fa[x]==y) continue; fa[y]=x;dep[y]=dep[x]+1;dfs1(y);size[x]+=size[y]; if(size[y]>size[son[x]]) son[x]=y; }}void dfs2(int x,int tp){ id[x]=++dfn;top[x]=tp; if(son[x]) dfs2(son[x],tp); for(int i=h[x];i;i=data[i].next){ int y=data[i].to; if(y==fa[x]||y==son[x]) continue; dfs2(y,y); }}void build(int p,int l,int r){ if(l==r) return; int mid=l+r>>1; build(p<<1,l,mid);build(p<<1|1,mid+1,r);}inline void pushup(int p){ tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum; tree[p].mx=max(tree[p<<1].mx,tree[p<<1|1].mx);}void change(int p,int l,int r,int x,int val){ if(l==r){tree[p].mx=tree[p].sum=val;return;} int mid=l+r>>1; if(x<=mid) change(p<<1,l,mid,x,val); else change(p<<1|1,mid+1,r,x,val); pushup(p);}int qsum(int p,int l,int r,int x,int y){ if(x<=l&&r<=y) return tree[p].sum; int mid=l+r>>1,res=0; if(x<=mid) res+=qsum(p<<1,l,mid,x,y); if(y>mid) res+=qsum(p<<1|1,mid+1,r,x,y); return res;}int qmax(int p,int l,int r,int x,int y){ if(x<=l&&r<=y) return tree[p].mx; int mid=l+r>>1,res=-inf; if(x<=mid) res=max(res,qmax(p<<1,l,mid,x,y)); if(y>mid) res=max(res,qmax(p<<1|1,mid+1,r,x,y)); return res;}int solvesum(int x,int y){ int res=0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); res+=qsum(1,1,n,id[top[x]],id[x]); x=fa[top[x]]; } if(id[x]>id[y]) swap(x,y); res+=qsum(1,1,n,id[x],id[y]); return res;}int solvemax(int x,int y){ int res=-inf; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); res=max(res,qmax(1,1,n,id[top[x]],id[x])); x=fa[top[x]]; } if(id[x]>id[y]) swap(x,y); res=max(res,qmax(1,1,n,id[x],id[y])); return res;}int main(){// freopen("a.in","r",stdin); n=read(); for(int i=1;i<n;++i){ int x=read(),y=read(); data[++num].to=y;data[num].next=h[x];h[x]=num; data[++num].to=x;data[num].next=h[y];h[y]=num; } dep[1]=1;dfs1(1);dfs2(1,1);build(1,1,n); for(int i=1;i<=n;++i) change(1,1,n,id[i],read());int q=read(); while(q--){ char op[10];scanf("%s",op+1);int x=read(),y=read(); if(op[2]=='H') change(1,1,n,id[x],y); if(op[2]=='S') printf("%d\n",solvesum(x,y)); if(op[2]=='M') printf("%d\n",solvemax(x,y)); } return 0;}
阅读全文
0 0
- bzoj1036 [ZJOI2008]树的统计(树链剖分)
- BZOJ1036 [ZJOI2008]树的统计Count 树链剖分
- bzoj1036 codevs2460: [ZJOI2008]树的统计 树链剖分
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
- 【bzoj1036】【树链剖分】【ZJOI2008】树的统计Count
- 【BZOJ1036】【ZJOI2008】【树的统计count】【树链剖分】
- BZOJ1036: [ZJOI2008]树的统计Count (树链剖分)
- bzoj1036: [ZJOI2008]树的统计Count - 树链剖分
- 【树链剖分】[BZOJ1036][ZJOI2008]树的统计Count
- [树链剖分] BZOJ1036: [ZJOI2008]树的统计Count
- [bzoj1036][ZJOI2008]树的统计Count 树链剖分
- 【bzoj1036】【树链剖分】 [ZJOI2008]树的统计Count
- BZOJ1036 [ZJOI2008]树的统计Count(树链剖分)
- [BZOJ1036][ZJOI2008]树的统计Count(树链剖分)
- [BZOJ1036][JZOJ2256]【ZJOI2008】树的统计(树链剖分模板)
- [BZOJ1036][ZJOI2008]树的统计Count(树链剖分)
- 树链剖分基础模板(BZOJ1036[ZJOI2008]树的统计Count)
- bzoj1036: [ZJOI2008]树的统计Count(树链剖分)
- 第一周、课时7:数据类型——boolean和数据类型的转换规律
- jmeter tcp取样器使用方法
- 织梦调用指定目录
- 开发手册
- 纯CSS实现SuckerFish二级(下拉)菜单
- bzoj1036 [ZJOI2008]树的统计(树链剖分)
- 事件分发全面认识
- ScrollerView 中RecyclerView上部有View时,View被顶出屏幕
- MySQL的rpm和源码两种安装操作
- retur在try中的返回情况
- 鼠标悬停“改变”图片
- [转]从一道面试题谈linux下fork的运行机制
- 使用mybatis以接口开发方式编程
- 针对Logstash吞吐量一次优化 .