bzoj 1036 树的统计
来源:互联网 发布:淘宝卖家工具 编辑:程序博客网 时间:2024/05/21 07:46
题目链接:点击打开链接
题目大意:有一棵树,30000个点,每个点有权值,接下来有20w个操作,分为三种,一是改变某个点的权值,二是询问从a到b的路径上的点的权值的最大值,三是询问a到b上点的权值和。
一道裸的树链剖分+线段树:
对于树上的路径问题,可以先进行轻重链划分,再用线段树解决。
轻重链剖分和点的重标号可以用dfs也可以用bfs
#include <iostream>#include <algorithm>#include <string.h>#include <vector>#include <cstdio>#define ll long long#define N 30005#define ls rt << 1#define rs rt << 1 | 1using namespace std;typedef struct{ int l,r,rt; ll maxn,sum;}node;typedef struct{ int v;}next;vector<next>edge[N<<1];node Tree[N<<4];int weight[N];int sz[N],son[N],maxn[N],q[N],Index[N],dep[N],fa[N],top[N],w[N],id[N];//id用来记录当前的点属于哪个链void PushUp(int rt){ Tree[rt].maxn = max(Tree[ls].maxn,Tree[rs].maxn); Tree[rt].sum = Tree[ls].sum + Tree[rs].sum;}void update(int p,int x,int rt){ if(p == Tree[rt].l && p ==Tree[rt].r){ Tree[rt].sum = x; Tree[rt].maxn = x; return ; } int mid; mid = (Tree[rt].l + Tree[rt].r) >> 1; if(p <= mid) update(p,x,ls); else update(p,x,rs); PushUp(rt);}void Build(int l,int r,int rt){ Tree[rt].l = l; Tree[rt].r = r; if(l == r){ Tree[rt].maxn = weight[Index[l]]; Tree[rt].sum = weight[Index[l]]; return ; } int mid; mid = (l + r) >> 1 ; Build(l,mid,ls); Build(mid+1,r,rs); PushUp(rt);}ll query(int op,int l,int r,int rt){ if(Tree[rt].l == l&&Tree[rt].r == r){ if(op == 0) return Tree[rt].maxn; else if(op == 1) return Tree[rt].sum; } int mid; mid =(Tree[rt].l+Tree[rt].r) >> 1; if(r <= mid) return query(op,l,r,ls); else if(l>mid) return query(op,l,r,rs); else { if(op == 0) return max(query(op,l,mid,ls),query(op,mid+1,r,rs)); else if(op == 1) return query(op,l,mid,ls)+query(op,mid+1,r,rs); }}int lca(int x,int y){//重链的id一定小于轻边的id while(id[x]!=id[y]){ if(id[x] > id[y]) swap(x,y); y = fa[top[y]]; } if(dep[x] > dep[y]) swap(x,y); return x;}ll op1(int Lca,int a,int b){//对路径上的每一段连续的线段进行查询 ll ret = -6000000000; while(1){ if(dep[top[a]] <=dep[Lca]){ ret = max(ret,query(0,w[Lca],w[a],1)); break; } else { ret = max(ret,query(0,w[top[a]],w[a],1)); a = fa[top[a]]; } } while(1){ if(dep[top[b]] <= dep[Lca]){ ret = max(ret,query(0,w[Lca],w[b],1)); break; } else { ret = max(ret,query(0,w[top[b]],w[b],1)); b = fa[top[b]]; } } return ret;}ll op2(int Lca,int a,int b){ ll ret = 0; while(1){ if(dep[top[a]] <=dep[Lca]){ ret +=query(1,w[Lca],w[a],1); break; } else { ret += query(1,w[top[a]],w[a],1); a = fa[top[a]]; } } while(1){ if(dep[top[b]] <=dep[Lca]){ ret += query(1,w[Lca],w[b],1); break; } else { ret += query(1,w[top[b]],w[b],1); b = fa[top[b]]; } } ret -= query(1,w[Lca],w[Lca],1); return ret;}void init(){ memset(maxn,-1,sizeof(maxn)); memset(sz,0,sizeof(sz)); memset(son,0,sizeof(son));}void bfs(int x){ int f,r,u,v,time,cnt; f = r = 0; q[r++] = x; dep[x] = 1; while(f<r){ u = q[f++]; for(int i = 0;i<edge[u].size();i++){ v = edge[u][i].v; if(v!=fa[u]){ fa[v] = u; dep[v] = dep[u] + 1; q[r++] = v; } } } for(int i = r-1;i>=0; i--){ sz[fa[q[i]]] += ++sz[q[i]]; if(maxn[fa[q[i]]] < sz[q[i]]){ maxn[fa[q[i]]] = sz[q[i]]; son[fa[q[i]]] = q[i]; } } fa[1] = 1; for(int i = 0;i < r; i++){ if(son[fa[q[i]]]!=q[i]){ top[q[i]] = q[i]; } else{ top[q[i]] = top[fa[q[i]]]; } } cnt = 0; f = 0;r = 1; q[0] = x; while(f<r){ u = q[f++]; if(top[u] == u) id[u] = ++cnt; else{ id[u] = id[top[u]]; } for(int i = 0;i<edge[u].size();i++){ v = edge[u][i].v; if(v!=fa[u]) q[r++] = v; } } f = 0;r = cnt = 1; q[0] = x; while(f<r){ u = q[f++]; v = u; Index[cnt] = v; w[v] = cnt++; while(son[v]){ for(int i = 0;i<edge[v].size();i++){ if(edge[v][i].v!=fa[v]&&edge[v][i].v!=son[v]){ q[r++] = edge[v][i].v; } } v = son[v]; Index[cnt] = v; w[v] = cnt++; } }}/*int dfs(int x,int f,int de){//dfs法 int s = 1,v,maxx = 0,tmp; fa[x] = f; dep[x] = de; for(int i=0;i<edge[x].size();i++){ v = edge[x][i].v; if(v!=f){ tmp = dfs(v,x,de+1); if(tmp > maxx){ son[x] = v; maxx = tmp; } s += tmp; } } return sz[x] = s;}int Time = 1,cnt = 0;void dfs2(int x,int tp){ int v; top[x] = tp; Index[Time] = x; w[x] = Time++; if(son[x]) dfs2(son[x],tp); for(int i = 0;i < edge[x].size();i++){ v = edge[x][i].v; if(v!=fa[x]){ if(v != son[x]) dfs2(v,v); } }}void deal(int x){ int f,r,u,v; f = 0;r = 1; q[0] = x; while(f<r){ u = q[f++]; if(top[u] == u) id[u] = ++cnt; else{ id[u] = id[top[u]]; } for(int i = 0;i<edge[u].size();i++){ v = edge[u][i].v; if(v!=fa[u]) q[r++] = v; } }}*/char opr[34];int main(){ init(); int n,a,b,q; ll ans; next tmp; cin>>n; for(int i = 0;i < n-1;i++){ scanf("%d%d",&a,&b); tmp.v = b; edge[a].push_back(tmp); tmp.v = a; edge[b].push_back(tmp); } for(int i = 1;i <= n; i++){ scanf("%d",&weight[i]); } bfs(1); //dfs(1,1,1); //dfs2(1,1); // deal(1); Build(1,n,1); cin>>q; int LCA; for(int i = 0;i < q; i++){ scanf("%s",opr); if(opr[0] == 'Q'){ scanf("%d%d",&a,&b); LCA = lca(a,b); if(opr[1] == 'M') ans = op1(LCA,a,b); else ans = op2(LCA,a,b); printf("%lld\n",ans); } else{ scanf("%d%d",&a,&b); update(w[a],b,1); } } return 0;}加上一组数据
141 22 52 66 116 121 33 71 44 84 99 1313 144 105 9 7 1 13 10 8 6 2 5 11 12 3 48QMAX 11 12QSUM 11 12QSUM 5 10QMAX 5 10QMAX 11 14QSUM 11 14QMAX 11 5QSUM 11 5
0 0
- Bzoj 1036 树的统计
- bzoj 1036 树的统计
- BZOJ 1036 树的统计
- BZOJ 1036 树的统计
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 树的统计 Count 树链剖分
- BZOJ 1036 树的统计 树链剖分
- 【BZOJ 1036】[ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count
- BZOJ-1036-树的统计Count
- BZOJ 1036 树的统计Count 树链剖分
- bzoj 1036[ZJOI] 树的统计
- BZOJ 1036 [ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- BZOJ 1036 [ZJOI2008]树的统计Count
- bzoj 1036 [ZJOI2008]树的统计Count
- 【bzoj】1036: [ZJOI2008]树的统计Count
- 用python实现一些数组的面试题
- 梦博——启程
- 悠闲的老鼠动画片,小鼠波波 Maisy教孩子学英语
- vmware安装linux无法全屏的解决方法
- hash函数_sumary
- bzoj 1036 树的统计
- 关于Ubuntu12.04安装
- URAL 1984. Dummy Guy(数学啊)
- C++输入输出流详解
- JQuery ajax
- 算法---快速排序
- 百度笔试面试题
- c++_set
- 最小公约数和最大公倍数模板