【ZJOI2008】树的统计
2016-05-14 13:22
344 查看
题目
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身
分析
只用单点修改的树链剖分模板题。include <cmath> #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> const int maxlongint=2147483647; using namespace std; struct trees { int v,mx,l,r; }tree[90000]; int d[90000],dson[90000],deep[90000],size[90000],fa[90000],top[90000],n,m,v[90000],bef[90000],tot,mi2[30]; int next[90000],last[90000],to[90000],po; int ans; int bj(int x,int y) { next[++tot]=last[x]; last[x]=tot; to[tot]=y; } int dg(int x) { size[x]=1; int mx=0; for(int i=last[x];i;i=next[i]) { if(to[i]!=fa[x]) { fa[to[i]]=x; deep[to[i]]=deep[x]+1; dg(to[i]); size[x]+=size[to[i]]; if(size[to[i]]>mx) { mx=size[to[i]]; dson[x]=to[i]; } } } } int dg1(int x) { bef[x]=++tot; d[tot]=x; if(top[x]==0) { top[x]=x; } if(dson[x]) { top[dson[x]]=top[x]; dg1(dson[x]); } for(int i=last[x];i;i=next[i]) { if(to[i]!=fa[x] && to[i]!=dson[x]) { dg1(to[i]); } } } int treechange(int l,int r,int pos,int aim,int value) { int mid=(l+r)/2; tree[pos].l=l; tree[pos].r=r; if(l==r) { tree[pos].v=value; tree[pos].mx=value; return 0; } if(aim<=mid) { treechange(l,mid,pos*2,aim,value); } else { treechange(mid+1,r,pos*2+1,aim,value); } tree[pos].v=tree[pos*2].v+tree[pos*2+1].v; tree[pos].mx=max(tree[pos*2].mx,tree[pos*2+1].mx); } int findmx(int l,int r,int pos,int aiml,int aimr) { int mid=(l+r)/2; if(l==aiml && r==aimr) { ans=max(ans,tree[pos].mx); return 0; } if(aimr<=mid) { findmx(l,mid,pos*2,aiml,aimr); } else if(aiml>mid) { findmx(mid+1,r,pos*2+1,aiml,aimr); } else { findmx(l,mid,pos*2,aiml,mid); findmx(mid+1,r,pos*2+1,mid+1,aimr); } } int findmax(int x,int y) { ans=-maxlongint; while(top[x]!=top[y]) { if(deep[top[x]]>=deep[top[y]]) { findmx(1,n,1,bef[top[x]],bef[x]); x=fa[top[x]]; } else { findmx(1,n,1,bef[top[y]],bef[y]); y=fa[top[y]]; } } if(deep[x]>=deep[y]) { findmx(1,n,1,bef[y],bef[x]); } else { findmx(1,n,1,bef[x],bef[y]); } printf("%d\n",ans); } int findsm(int l,int r,int pos,int aiml,int aimr) { int mid=(l+r)/2; if(l==aiml && r==aimr) { ans+=tree[pos].v; return 0; } if(aimr<=mid) { findsm(l,mid,pos*2,aiml,aimr); } else if(aiml>mid) { findsm(mid+1,r,pos*2+1,aiml,aimr); } else { findsm(l,mid,pos*2,aiml,mid); findsm(mid+1,r,pos*2+1,mid+1,aimr); } } int findsum(int x,int y) { ans=0; while(top[x]!=top[y]) { if(deep[top[x]]>=deep[top[y]]) { findsm(1,n,1,bef[top[x]],bef[x]); x=fa[top[x]]; } else { findsm(1,n,1,bef[top[y]],bef[y]); y=fa[top[y]]; } } if(deep[x]>=deep[y]) { findsm(1,n,1,bef[y],bef[x]); } else { findsm(1,n,1,bef[x],bef[y]); } printf("%d\n",ans); } int main() { mi2[1]=1; for(int i=2;i<=25;i++) mi2[i]=mi2[i-1]*2; scanf("%d",&n); for(int i=1;i<=n-1;i++) { int x,y; scanf("%d%d",&x,&y); bj(x,y); bj(y,x); } deep[1]=1; dg(1); tot=0; dg1(1); for(int i=1;i<=90000-1;i++) tree[i].mx=-maxlongint; for(int i=1;i<=25;i++) { if(mi2[i]*2>=tot) { po=mi2[i]*2-1; break; } } for(int i=1;i<=n;i++) { int x; scanf("%d",&x); treechange(1,n,1,bef[i],x); } scanf("%d\n",&m); char c; for(int i=1;i<=m;i++) { c=getchar(); if(c=='C') { int x,y; scanf("HANGE %d %d\n",&x,&y); treechange(1,n,1,bef[x],y); } else { c=getchar(); if(c=='M') { int x,y; scanf("AX %d %d\n",&x,&y); findmax(x,y); } else { int x,y; scanf("UM %d %d\n",&x,&y); findsum(x,y); } } } }
相关文章推荐
- 线程的基本概念状态和之间的关系
- SerializeField和HideInInspector
- 代码能力并不是你最重要的能力 !! ---IBM数据摇滚节参赛感悟
- 代码能力并不是你最重要的能力 !! ---IBM数据摇滚节参赛感悟
- 线程的基本概念,状态,和状态之间的关系
- maven基础篇(2)-基本配置说明
- 一种为使用Log4j的分布式应用提供云端日志服务的方法
- 802.11MAC帧分析
- 线性表的顺序存储——顺序表
- 排序 希尔排序
- boost.asio学习
- 数据结构(c)——排序算法
- 亚信笔试题
- 求x的y次幂
- 3的n次幂 mod 19
- 出栈次序 卡兰特数
- 搜索引擎选型调研之Flume1.6+Elasticsearch2.3.1
- Win7下硬盘安装Linux双系统
- 学习进度条10
- 百度前端学院task33源码及总结——听指令的小方块