BZOJ 1036: [ZJOI2008]树的统计Count(树链剖分 点权)
2016-10-26 16:17
411 查看
题目链接
题意:给出一个树,告诉每个点的权值,然后有修改操作,还有询问(u,v)路径上的最大值,(u,v)路径的和
树链剖分啦,一般分为点权和边权,剖分部分不变,只是用其他数据结构处理的时候注意一下,点权可以可以转换为该点与父边的权值,就变为了边权,这样就相于给根节点来了一个虚拟的父亲(代码中不用体现),
对于剖分的学习,动手自己剖分一遍,就明白了,第二个dfs就是把重边连城链,其实就是给边编号,使得能用其他数据结构处理,比如线段树。
题意:给出一个树,告诉每个点的权值,然后有修改操作,还有询问(u,v)路径上的最大值,(u,v)路径的和
树链剖分啦,一般分为点权和边权,剖分部分不变,只是用其他数据结构处理的时候注意一下,点权可以可以转换为该点与父边的权值,就变为了边权,这样就相于给根节点来了一个虚拟的父亲(代码中不用体现),
对于剖分的学习,动手自己剖分一遍,就明白了,第二个dfs就是把重边连城链,其实就是给边编号,使得能用其他数据结构处理,比如线段树。
//#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<cstring> #include<set> #include<map> #include<string> #include<cassert> using namespace std; #define cl(a,b) memset(a,b,sizeof(a)) #define fastIO ios::sync_with_stdio(false);cin.tie(0); #define ll unsigned long long #define pb push_back #define gcd __gcd #define For(i,j,k) for(int i=(j);i<=k;i++) #define lowbit(i) (i&(-i)) #define _(x) printf("%d\n",x) typedef vector<ll> vec; typedef pair<int,int> PI; const double EPS = 1e-8; const int maxn = 3e5+100; const int inf = 1 << 28; struct Edge{ int next,to; }edge[maxn]; int val[maxn]; int head[maxn],tot; int top[maxn]; int fa[maxn]; int p[maxn]; int fp[maxn]; int num[maxn]; int son[maxn]; int deep[maxn]; int pos; void init(){ tot=0; memset(head,-1,sizeof(head)); pos=0; memset(son,-1,sizeof(son)); } void addEdge(int u,int v){ edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++; } void dfs(int u,int pre,int d){//fa,num,deep,son fa[u]=pre; num[u]=1; deep[u]=d; for(int i=head[u];~i;i=edge[i].next){ int v=edge[i].to; if(v!=pre){ dfs(v,u,d+1); num[u]+=num[v]; if(son[u]==-1||num[son[u]]<num[v])son[u]=v; } } } void getpos(int u,int sp){//fp,p,top,编码 top[u]=sp; p[u]=pos++; fp[p[u]]=u; if(son[u]==-1)return; getpos(son[u],sp); for(int i=head[u];~i;i=edge[i].next){ int v=edge[i].to; if(v!=fa[u]&&v!=son[u])getpos(v,v); } } int Max[maxn<<2]; int Sum[maxn<<2]; void push_up(int rt){ Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1]; } void build(int rt,int l,int r){ if(l==r){ Max[rt]=Sum[rt]=val[fp[l]]; return ; } int mid=l+r>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); push_up(rt); } void update(int rt,int l,int r,int i,int v){ if(l==i&&i==r){ Sum[rt]=Max[rt]=v; return; } int mid=l+r>>1; if(i<=mid)update(rt<<1,l,mid,i,v); else update(rt<<1|1,mid+1,r,i,v); push_up(rt); } int queryMax(int rt,int l,int r,int x,int y){ if(x<=l&&r<=y){ return Max[rt]; } int mid=l+r>>1; int ans=-(1<<28);; if(x<=mid) ans=max(ans,queryMax(rt<<1,l,mid,x,y)); if(y> mid) ans=max(ans,queryMax(rt<<1|1,mid+1,r,x,y)); return ans; } int querySum(int rt,int l,int r,int x,int y){ if(x<=l&&r<=y){ return Sum[rt]; } int mid=l+r>>1; int ans=0; if(x<=mid)ans+=querySum(rt<<1,l,mid,x,y); if(y>mid)ans+=querySum(rt<<1|1,mid+1,r,x,y); return ans; } int findSum(int u,int v){ int f1=top[u],f2=top[v]; int ans=0; while(f1!=f2){ if(deep[f1]<deep[f2]){ swap(f1,f2); swap(u,v); } ans+=querySum(1,0,pos-1,p[f1],p[u]); u=fa[f1];f1=top[u]; } if(deep[u]>deep[v])swap(u,v); ans+=querySum(1,0,pos-1,p[u],p[v]); return ans; } int findMax(int u,int v){ int f1=top[u],f2=top[v]; int ans=-(1<<28); while(f1!=f2){ if(deep[f1]<deep[f2]){ swap(f1,f2); swap(u,v); } ans=max(ans,queryMax(1,0,pos-1,p[f1],p[u])); u=fa[f1];f1=top[u]; } if(deep[u]>deep[v])swap(u,v); ans=max(ans,queryMax(1,0,pos-1,p[u],p[v])); return ans; } int main(){ int n,q; while(~scanf("%d",&n)){ init(); for(int i=0;i<n-1;i++){ int x,y; scanf("%d%d",&x,&y); addEdge(x,y);addEdge(y,x); } for(int i=1;i<=n;i++){ scanf("%d",&val[i]); } dfs(1,0,0); getpos(1,1); build(1,0,pos-1); scanf("%d",&q); char op[44]; while(q--){ int x,y; scanf("%s%d%d",op,&x,&y); if(op[1]=='M'){ printf("%d\n",findMax(x,y)); } else if(op[1]=='S'){ printf("%d\n",findSum(x,y)); } else { update(1,0,pos-1,p[x],y); } } } return 0; } /* 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 */
相关文章推荐
- BZOJ 1036 [ZJOI2008]树的统计Count 树链剖分裸题
- |BZOJ 1036|树链剖分|线段树|[ZJOI2008]树的统计Count
- 树链剖分 - BZOJ 1036: [ZJOI2008]树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count(树链剖分)
- 【bzoj1036】[ZJOI2008]树的统计Count(树链剖分)/(动态树)
- 树链剖分(bzoj 1036: [ZJOI2008]树的统计Count)
- bzoj1036[ZJOI2008]树的统计Count 树链剖分+线段树
- 【BZOJ 1036】[ZJOI2008]树的统计Count 【树链剖分+线段树】
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- [BZOJ1036][ZJOI2008]树的统计Count(树链剖分)
- BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分 + 线段树)
- BZOJ1036:[ZJOI2008]树的统计Count 树链剖分 / LCT
- [树链剖分] BZOJ1036: [ZJOI2008]树的统计Count
- BZOJ1036 [ZJOI2008]树的统计Count 树链剖分
- [ZJOI2008]树的统计Count bzoj1036 树链剖分
- bzoj 1036: [ZJOI2008]树的统计Count——树链剖分
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
- bzoj 1036: [ZJOI2008]树的统计Count (树链剖分)