bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
2017-12-22 20:25
519 查看
题目大意:
给你一颗树,每个点有权值,要你求出一个点到另一个点路径的最大权值,或者是权值和,还要支持修改权值的问题。思路:
树链剖分的模板题。树链剖分大概就是把书上的链给按一定方法拆开,然后每一段去一个hash值,放入线段树中去维护他的区间值。这里有一个大佬的博客:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html
程序:
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #define inf 0x7fffffff #define maxn 30005 #define maxm 60005 using namespace std; int pos[maxn],top[maxn],fa[maxn],size[maxn],son[maxn],dep[maxn],a[maxn],last[maxn]; int n,cnt,sz; struct data{int w,next;}e[maxm]; struct tree{int l,r,mx,sum;}t[100001]; void add(int u,int v){ e[++cnt].next=last[u]; e[cnt].w=v; last[u]=cnt; e[++cnt].next=last[v]; e[cnt].w=u; last[v]=cnt; } void init(){ int u,v; scanf("%d",&n); for (int i=1;i<=n-1;i++){ scanf("%d%d",&u,&v); add(u,v); } for (int i=1;i<=n;i++){ scanf("%d",&a[i]); } } void dfs1(int x){ size[x]=1; for (int i=last[x];i;i=e[i].next){ if (fa[x]==e[i].w) continue; fa[e[i].w]=x; dep[e[i].w]=dep[x]+1; dfs1(e[i].w); size[x]+=size[e[i].w]; } } void dfs2(int x,int chain){ int k=0; sz++; pos[x]=sz; top[x]=chain; for (int i=last[x];i;i=e[i].next){ if (fa[x]!=e[i].w&&size[e[i].w]>size[k]) k=e[i].w; } if (k==0) return; dfs2(k,chain); for (int i=last[x];i;i=e[i].next){ if (e[i].w!=fa[x]&&e[i].w!=k) dfs2(e[i].w,e[i].w); } } void build(int d,int l,int r){ t[d].l=l; t[d].r=r; if (l==r) return; int mid=(l+r)/2; build(d*2,l,mid); build(d*2+1,mid+1,r); } void change(int d,int x,int y){ if (t[d].l==t[d].r) { t[d].sum=t[d].mx=y; return; } int mid=(t[d].l+t[d].r)/2; if (x<=mid) change(d*2,x,y); else change(d*2+1,x,y); t[d].sum=t[d*2].sum+t[d*2+1].sum; t[d].mx=max(t[d*2].mx,t[d*2+1].mx); } int querymax(int d,int x,int y){ if (t[d].l==x&&t[d].r==y) return t[d].mx; int mid=(t[d].l+t[d].r)/2; if (y<=mid) return querymax(d*2,x,y); else if (x>mid) return querymax(d*2+1,x,y); else return max(querymax(d*2,x,mid),querymax(d*2+1,mid+1,y)); } int solvemax(int x,int y){ int mx=-inf; while (top[x]!=top[y]){ if (dep[top[x]]<dep[top[y]]) swap(x,y); mx=max(mx,querymax(1,pos[top[x]],pos[x])); x=fa[top[x]]; } if (dep[x]>dep[y]) swap(x,y); mx=max(mx,querymax(1,pos[x],pos[y])); return mx; } int querysum(int d,int x,int y){ if (t[d].l==x&&t[d].r==y) return t[d].sum; int mid=(t[d].l+t[d].r)/2; if (y<=mid) return querysum(d*2,x,y); else if (x>mid) return querysum(d*2+1,x,y); else return querysum(d*2,x,mid)+querysum(d*2+1,mid+1,y); } int solvesum(int x, int y){ int sum=0; while (top[x]!=top[y]){ if (dep[top[x]]<dep[top[y]]) swap(x,y); sum+=querysum(1,pos[top[x]],pos[x]); x=fa[top[x]]; } if (dep[x]>dep[y]) swap(x,y); sum+=querysum(1,pos[x],pos[y]); return sum; } int solve() { build(1,1,n); for (int i=1;i<=n;i++) change(1,pos[i],a[i]); int q; scanf("%d",&q); char ch[10]; int x,y; for (int i=1;i<=q;i++){ scanf("%s%d%d",ch,&x,&y); if (ch[0]=='C') change(1,pos[x],y); else { if (ch[1]=='M') printf("%d\n",solvemax(x,y)); else printf("%d\n",solvesum(x,y)); } } } int main(){ init(); dfs1(1); dfs2(1,1); solve(); return 0; }
相关文章推荐
- bzoj1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- 【BZOJ】1036 [ZJOI2008]树的统计Count 树链剖分+线段树
- 【bzoj1036】[ZJOI2008]树的统计Count 树链剖分+线段树
- 【bzoj1036】[ZJOI2008]树的统计Count 树链剖分+线段树
- bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分+线段树)
- 【BZOJ1036】[ZJOI2008]树的统计Count(树链剖分+线段树)
- 【bzoj1036】[ZJOI2008]树的统计Count
- bzoj1036 [ZJOI2008]树的统计Count
- BZOJ1036 [ZJOI2008]树的统计Count
- BZOJ1036 [ZJOI2008]树的统计Count
- 文章标题 BZOJ 1036 : [ZJOI2008]树的统计Count (树链剖分 + 线段树)
- bzoj1036: [ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count(树链剖分)
- 【bzoj1036】[ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ1036 [ZJOI2008]树的统计Count(树链剖分)
- bzoj1036 [ZJOI2008]树的统计Count
- BZOJ1036 [ZJOI2008]树的统计Count 树链剖分