BZOJ 1036: [ZJOI2008]树的统计Count(树链剖分(点权))
2017-05-24 13:21
369 查看
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 16631 Solved: 6756
[Submit][Status][Discuss]
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. 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”的形式给出。
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
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
题解:树链剖分后,用一棵线段树维护最大值和和值。
代码:
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 16631 Solved: 6756
[Submit][Status][Discuss]
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. 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”的形式给出。
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
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
题解:树链剖分后,用一棵线段树维护最大值和和值。
代码:
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; int cnt,u,v,k,tot,n,q; int dep ,fa ,siz ,son ; int sum[N<<2],mx[N<<2]; int a ; struct node{int to,next;}edge[N<<2]; int head[N<<2]; void add(int u,int v) { edge[cnt].to=v,edge[cnt].next=head[u],head[u]=cnt++; edge[cnt].to=u,edge[cnt].next=head[v],head[v]=cnt++; } void dfs1(int u,int f,int d) { dep[u]=d,fa[u]=f,siz[u]=1,son[u]=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==f)continue; dfs1(v,u,d+1); siz[u]+=siz[v]; if(siz[son[u]]<siz[v]) son[u]=v; } } int top ,pre ,tree ; void dfs2(int u,int tp) { top[u]=tp,tree[u]=++tot,pre[tree[u]]=u; if(!son[u]) return ; dfs2(son[u],tp); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==fa[u]||v==son[u]) continue; dfs2(v,v); } } void init() { tot=0; cnt=0; memset(head,-1,sizeof(head)); } void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; mx[rt]=max(mx[rt<<1],mx[rt<<1|1]); } void build(int l,int r,int rt) { if(l==r) { sum[rt]=mx[rt]=a[pre[l]]; return ; } int mid=(r+l)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt); } void update(int l,int r,int pos,int val,int rt) { if(l==r) { sum[rt]=mx[rt]=val; return ; } int mid=(r+l)>>1; if(pos<=mid) update(l,mid,pos,val,rt<<1); else update(mid+1,r,pos,val,rt<<1|1); pushup(rt); } int query_max(int l,int r,int ll,int rr,int rt) { if(ll<=l&&rr>=r) { return mx[rt]; } int ans=-1e8; int mid=(r+l)>>1; if(ll<=mid) ans=max(ans,query_max(l,mid,ll,rr,rt<<1)); if(rr>mid) ans=max(ans,query_max(mid+1,r,ll,rr,rt<<1|1)); return ans; } int query_sum(int l,int r,int ll,int rr,int rt) { if(ll<=l&&rr>=r) { return sum[rt]; } int ans=0; int mid=(r+l)>>1; if(ll<=mid) ans+=query_sum(l,mid,ll,rr,rt<<1); if(rr>mid) ans+=query_sum(mid+1,r,ll,rr,rt<<1|1); return ans; } int find_sum(int x,int y) { int ans=0; int fx=top[x],fy=top[y]; while(fx!=fy) { if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy); ans+=query_sum(1,n,tree[fx],tree[x],1); x=fa[fx],fx=top[x]; } if(dep[x]>dep[y]) swap(x,y); ans+=query_sum(1,n,tree[x],tree[y],1); return ans; } int find_max(int x,int y) { int ans=-1e6; int fx=top[x],fy=top[y]; while(fx!=fy) { if(dep[fx]<dep[fy]) swap(x,y),swap(fx,fy); ans=max(ans,query_max(1,n,tree[fx],tree[x],1)); x=fa[fx],fx=top[x]; } if(dep[x]>dep[y]) swap(x,y); ans=max(ans,query_max(1,n,tree[x],tree[y],1)); return ans; } char str[10]; int main() { init(); scanf("%d",&n); for(int i=1;i<n;i++) { scanf("%d%d",&u,&v); add(u,v); } for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } dfs1(1,0,1),dfs2(1,1); build(1,n,1); scanf("%d",&q); while(q--) { scanf("%s%d%d",str,&u,&v); if(str[0]=='C') { update(1,n,tree[u],v,1); a[u]=v; } else if(str[1]=='M') { printf("%d\n",find_max(u,v)); } else { printf("%d\n",find_sum(u,v)); } } return 0; }
相关文章推荐
- bzoj 1036: [ZJOI2008]树的统计Count——树链剖分
- [树链剖分] BZOJ1036: [ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count (树链剖分)
- [bzoj1036][ZJOI2008]树的统计Count 树链剖分
- 树链剖分教程 & bzoj 1036 [ZJOI2008] 树的统计 Count 题解
- Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT
- bzoj 1036: [ZJOI2008]树的统计Count(树链剖分)
- [ZJOI2008]树的统计Count bzoj1036 树链剖分
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- bzoj 1036: [ZJOI2008]树的统计Count(树链剖分)
- bzoj 1036 [ZJOI2008]树的统计Count (树链剖分 + 线段树)
- bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)
- 【BZOJ1036】【ZJOI2008】树的统计Count 树链剖分裸题
- 【bzoj1036】【树链剖分】 [ZJOI2008]树的统计Count
- 【树链剖分】[BZOJ1036][ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count 【树链剖分】
- _bzoj1036 [ZJOI2008]树的统计Count【树链剖分】
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】