JZOJ 2256. 【BZOJ 2256】【ZJOI 2008】树的统计
来源:互联网 发布:乐乎电脑版 编辑:程序博客网 时间:2024/05/01 22:26
Description
一棵树上有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本身
Input
输入文件的第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16
Hint
【数据说明】
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Solution
这题的操作一看就像线段树,可是操作却在树上,怎么办呢?
于是,我们就要用到一种高级算法——树链剖分!
这道题是树链剖分的模板题,操作相对简单。
详细请见:树链剖分详解
接着套上线段树就能实现这些询问了!
下见代码:
Code
#include<cstdio>#include<algorithm>using namespace std;const int N=30001;struct data{ int sum,max,l,r;}f[N<<2];int tot,num;int first[N],next[N<<1],en[N<<1];int fa[N],dep[N],size[N],son[N],top[N];int tree[N],pre[N];int a[N];char s[7];inline int read(){ int data=0,w=1; char ch=0; while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar(); if(ch=='-') ch=getchar(),w=-1; while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar(); return data*w;}inline void insert(int x,int y){ next[++tot]=first[x]; first[x]=tot; en[tot]=y;}inline void dfs1(int x){ dep[x]=dep[fa[x]]+1; size[x]=1; for(int i=first[x];i;i=next[i]) if(en[i]!=fa[x]) { fa[en[i]]=x; dfs1(en[i]); size[x]+=size[en[i]]; if(!son[x] || size[son[x]]<size[en[i]]) son[x]=en[i]; }}inline void dfs2(int x,int y){ top[pre[tree[x]=++num]=x]=y; if(!son[x]) return; dfs2(son[x],y); for(int i=first[x];i;i=next[i]) if(en[i]!=fa[x] && en[i]!=son[x]) dfs2(en[i],en[i]);}inline int max(int x,int y){ return x>y?x:y;}inline void update(int v){ int ls=v<<1,rs=ls+1; f[v].sum=f[ls].sum+f[rs].sum; f[v].max=max(f[ls].max,f[rs].max);}inline void make(int v,int l,int r){ f[v].l=l,f[v].r=r; if(l==r) { f[v].sum=f[v].max=a[pre[l]]; return; } int mid=(l+r)>>1; make(v<<1,l,mid); make((v<<1)+1,mid+1,r); update(v);}inline void change(int v,int x,int add){ if(f[v].l==f[v].r) { f[v].max+=add; f[v].sum+=add; return; } int mid=(f[v].l+f[v].r)>>1; if(x<=mid) change(v<<1,x,add); else change((v<<1)+1,x,add); update(v);}inline int dfs_max(int v,int x,int y){ if(f[v].l>=x && f[v].r<=y) return f[v].max; int mid=(f[v].l+f[v].r)>>1,mx=-1e9; if(x<=mid) mx=dfs_max(v<<1,x,y); if(y>mid) mx=max(mx,dfs_max((v<<1)+1,x,y)); update(v); return mx;}inline int dfs_sum(int v,int x,int y){ if(f[v].l>=x && f[v].r<=y) return f[v].sum; int mid=(f[v].l+f[v].r)>>1,sum=0; if(x<=mid) sum+=dfs_sum(v<<1,x,y); if(y>mid) sum+=dfs_sum((v<<1)+1,x,y); update(v); return sum;}inline int find_max(int x,int y){ int f1=top[x],f2=top[y],ans=-1e9; while(f1!=f2) { if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); ans=max(ans,dfs_max(1,tree[f1],tree[x])); x=fa[f1],f1=top[x]; } if(dep[x]>dep[y]) swap(x,y); ans=max(ans,dfs_max(1,tree[x],tree[y])); return ans;}inline int find_sum(int x,int y){ int f1=top[x],f2=top[y],ans=0; while(f1!=f2) { if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y); ans+=dfs_sum(1,tree[f1],tree[x]); x=fa[f1],f1=top[x]; } if(dep[x]>dep[y]) swap(x,y); ans+=dfs_sum(1,tree[x],tree[y]); return ans; }int main(){ int n=read(); for(int i=1;i<n;i++) { int x=read(),y=read(); insert(x,y); insert(y,x); } for(int i=1;i<=n;i++) a[i]=read(); dfs1(1); dfs2(1,1); make(1,1,n); int q=read(); while(q--) { scanf("%s",s); int x=read(),y=read(); if(s[1]=='H') { change(1,tree[x],y-a[x]); a[x]=y; }else printf("%d\n",s[1]=='M'?find_max(x,y):find_sum(x,y)); } return 0;}
- JZOJ 2256. 【BZOJ 2256】【ZJOI 2008】树的统计
- [BZOJ 1036] ZJOI 2008 树的统计Count · 树链剖分
- bzoj 1036[ZJOI] 树的统计
- ZJOI 2008 树的统计
- BZOJ 1036 [zjoi 2008] 数的统计 (树链剖分)
- ZJOI 树的统计 [五星]
- ZJOI 2008 树的统计(树链剖分+线段树)
- [BZOJ 1058][ZJOI 2007]报表统计 平衡树+线段树
- BZOJ 1058 ZJOI 2007 报表统计 平衡树
- codevs 2460 [ZJOI] 树的统计 树剖
- 【BZOJ 1058】【ZJOI 2007】报表统计【Treap】
- JZOJ 2256【ZJOI2008】树的统计
- BZOJ 2657 ZJOI 2012 旅游(journey) 树的直径
- BZOJ 1040 [ZJOI 2008] 树DP 解题报告
- BZOJ 1833 [ZJOI 2010] 数字统计 (数位DP)
- BZOJ 1038 [ZJOI 2008] 瞭望塔
- BZOJ 1036 [ZJOI 2008] 树链剖分 解题报告
- 【BZOJ 4574】【ZJOI 2016】线段树
- sql经纬度查询
- 完全分布式安装Hadoop,Hive,Hbase,Hwi,Zookeeper-500行说明
- SpringMVC 获取项目路径
- CSS清除浮动,什么时候需要清除浮动,清除浮动都有哪些方法
- MySql语句(Like模糊匹配)
- JZOJ 2256. 【BZOJ 2256】【ZJOI 2008】树的统计
- unity3d小技巧之锁定场景物体防止被误选中
- 【C++】友元函数
- 如何给pajek中的节点和边着色?
- JAVAWEB 当中 JSP 出现中文乱码的解决方案
- crontab命令参数使用
- ubuntu boot分区不足问题之起死回生
- C++ 内联函数
- Zurmo开发的小技巧总结