bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
来源:互联网 发布:金蝶k3软件多少钱 编辑:程序博客网 时间:2024/06/05 17:33
题目大意:
给你一颗树,每个点有权值,要你求出一个点到另一个点路径的最大权值,或者是权值和,还要支持修改权值的问题。
思路:
树链剖分的模板题。树链剖分大概就是把书上的链给按一定方法拆开,然后每一段去一个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 60005using 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;}
阅读全文
0 0
- 【BZOJ】1036 [ZJOI2008]树的统计Count 树链剖分+线段树
- bzoj 1036 [ZJOI2008]树的统计Count 线段树+树链剖分
- bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- 【BZOJ 1036】[ZJOI2008]树的统计Count 【树链剖分+线段树】
- BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分+线段树)
- |BZOJ 1036|树链剖分|线段树|[ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- 【BZOJ 1036】[ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- bzoj 1036 [ZJOI2008]树的统计Count
- 【bzoj】1036: [ZJOI2008]树的统计Count
- [BZOJ]1036: [ZJOI2008]树的统计Count
- 小学生进位
- 软件工程思维导图
- 12.21
- 深入super,看Python如何解决钻石继承难题
- GAN学习笔记(1):GAN综述
- bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- 矩阵快速幂&递推的妙解
- angularjs值服务
- Django内置过滤器详解附代码附效果图--附全部内置过滤器帮助文档
- AI
- C语言程序设计教程(第三版)课后习题11.5
- 人员分配[模板_最大匹配]
- BZOJ[2084][Poi2010]Antisymmetry Manacher
- wpf中放置图片