BZOJ 1036 [ZJOI2008]树的统计Count
2016-10-13 22:41
267 查看
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本身
【题目分析】
树链剖分+线段树。
【代码】
一棵树上有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 <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int n,root=1,node,q,x,y; int h[30001],ne[60001],to[60001],en=0; int fa[30001],dep[30001],son[30001],siz[30001],top[30001],pos[30001],w[30001]; int v[30001]; char opt[11]; struct node{ int l,r,max,sum; }t[30001*8]; int read() { int ret=0,f=1; char ch=getchar(); while (ch>'9'||ch<'0') { if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9') { ret*=10; ret+=ch-'0'; ch=getchar(); } return ret*f; } void add(int a,int b) {ne[en]=h[a];to[en]=b;h[a]=en++;} void dfs1(int k) { siz[k]=1; for (int i=h[k];i>=0;i=ne[i]) { if (to[i]!=fa[k]) { fa[to[i]]=k; dep[to[i]]=dep[k]+1; dfs1(to[i]); siz[k]+=siz[to[i]]; if (siz[to[i]]>siz[son[k]]) son[k]=to[i]; } } } void dfs2(int k,int tp) { top[k]=tp; pos[k]=++node; v[pos[k]]=w[k]; if (son[k]==0) return ; dfs2(son[k],tp); for (int i=h[k];i>=0;i=ne[i]) if (to[i]!=son[k]&&to[i]!=fa[k]) dfs2(to[i],to[i]); } void update(int k,int x,int y) { if (t[k].l==t[k].r) { t[k].sum=t[k].max=v[t[k].l]; return ; } if (x<=(t[k].l+t[k].r)/2) update(k*2,x,y); else update(k*2+1,x,y); t[k].sum=t[k*2].sum+t[k*2+1].sum; t[k].max=max(t[k*2].max,t[k*2+1].max); } int qmax(int k,int L,int R) { if (t[k].r<L||t[k].l>R) return -0x3f3f3f3f; if (t[k].l>=L&&t[k].r<=R) return t[k].max; return max(qmax(k*2,L,R),qmax(k*2+1,L,R)); } int qsum(int k,int L,int R) { if (t[k].r<L||t[k].l>R) return 0; if (t[k].l>=L&&t[k].r<=R) return t[k].sum; return qsum(k*2,L,R)+qsum(k*2+1,L,R); } void build(int k,int L,int R) { t[k].l=L;t[k].r=R; if (L==R) { t[k].sum=t[k].max=v[L]; return; } build(k*2,L,(L+R)/2); build(k*2+1,(L+R)/2+1,R); t[k].sum=t[k*2].sum+t[k*2+1].sum; t[k].max=max(t[k*2].max,t[k*2+1].max); } int main() { memset(h,-1,sizeof h); n=read(); for (int i=1;i<n;++i) { int a,b; a=read();b=read(); add(a,b); add(b,a); } for (int i=1;i<=n;++i) w[i]=read(); dfs1(root); dfs2(root,root); build(1,1,n); q=read(); while (q--) { scanf("%s",opt); if (opt[0]=='C') { x=read();y=read(); w[x]=y; v[pos[x]]=y; update(1,pos[x],y); } else if (opt[1]=='M') { int ans=-0x3f3f3f3f; x=read();y=read(); while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); ans=max(ans,qmax(1,pos[top[x]],pos[x])); x=fa[top[x]]; } if (dep[x]<dep[y]) swap(x,y); ans=max(ans,qmax(1,pos[y],pos[x])); printf("%d\n",ans); } else { int ans=0; x=read();y=read(); while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); ans+=qsum(1,pos[top[x]],pos[x]); x=fa[top[x]]; } if (dep[x]<dep[y]) swap(x,y); ans+=qsum(1,pos[y],pos[x]); printf("%d\n",ans); } } }
相关文章推荐
- BZOJ 1036: [ZJOI2008]树的统计Count
- bzoj 1036 [ZJOI2008]树的统计Count
- bzoj1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008] 树的统计Count
- BZOJ1036 [ZJOI2008]树的统计Count
- 【ZJOI2008】【BZOJ1036】树的统计Count
- 【bzoj1036】[ZJOI2008]树的统计Count
- bzoj1036 [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count==树剖裸题
- [BZOJ]1036: [ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count
- BZOJ1036: [ZJOI2008]树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count
- 【BZOJ 1036】【ZJOI 2008】树的统计Count
- Bzoj 1036: [ZJOI2008]树的统计Count
- bzoj1036 [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- bzoj1036[ZJOI2008]树的统计Count
- 【BZOJ 1036】[ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分