BZOJ1036: [ZJOI2008]树的统计Count (树链剖分)
来源:互联网 发布:无线网络连接软件 编辑:程序博客网 时间:2024/04/19 20:52
传送门
这是一道树链剖分的基础题目,只需要用线段树来维护重链上的节点信息,轻链一条一条爬就行了,在查询的时候可以先求出LCA然后查询两个点到LCA的信息然后合并就行了。
代码:
/************************************************************** Problem: 1036 User: geng4512 Language: C++ Result: Accepted Time:3064 ms Memory:5188 kb****************************************************************/#include<cstdio>#define MAXN 30005struct node {int v; node *nxt;} Edge[MAXN<<1], *Adj[MAXN], *M = Edge;inline void Add(int u, int v) { ++ M; M->v = v; M->nxt = Adj[u]; Adj[u] = M; }inline int Max(int a, int b) {return a > b ? a : b;}struct Seg{int l, r, mx, sum;} t[MAXN<<2];char c, f;inline void GET(int &n) { f = 1; n = 0; do{c = getchar(); if(c == '-') f = -1; }while('0' > c || c > '9'); while('0' <= c && c <= '9') {n=n*10+c-'0';c=getchar();} n *= f;}int n, fa[MAXN], dep[MAXN], dcnt, pos[MAXN];int sz[MAXN], htp[MAXN], hsn[MAXN], a[MAXN];int px[MAXN], q, rev[MAXN];/************ 线段树相关 ******************/void Build(int i, int l, int r) { t[i].l = l; t[i].r = r; if(l == r) { px[l] = i; t[i].sum = t[i].mx = a[rev[l]]; return; } int mid = (l+r)>>1; Build(i<<1, l, mid); Build(i<<1|1, mid+1, r); t[i].mx = Max(t[i<<1].mx, t[i<<1|1].mx); t[i].sum = t[i<<1].sum + t[i<<1|1].sum;}void Ins(int x, int v) { int p = px[x]; t[p].mx = t[p].sum = v; p >>= 1; while(p) { t[p].mx = Max(t[p<<1].mx, t[p<<1|1].mx); t[p].sum = t[p<<1].sum + t[p<<1|1].sum; p >>= 1; }}int Qmx(int i, int L, int R) { if(t[i].r < L || t[i].l > R) return -0x3f3f3f3f; if(L <= t[i].l && t[i].r <= R) return t[i].mx; return Max(Qmx(i<<1, L, R), Qmx(i<<1|1, L, R));}int Qsm(int i, int L, int R) { if(t[i].r < L || t[i].l > R) return 0; if(L <= t[i].l && t[i].r <= R) return t[i].sum; return Qsm(i<<1, L, R) + Qsm(i<<1|1, L, R);}/****************************************/int tmp;inline void Swap(int &a, int &b) {tmp = a; a = b; b = tmp;}inline int LCA(int a, int b) { while(htp[a] != htp[b]) { if(dep[htp[a]] < dep[htp[b]]) Swap(a, b); a = fa[htp[a]]; } return dep[a] < dep[b] ? a : b;}inline int sum(int a, int b) { int sum = 0; while(htp[a] != htp[b]) { //查重链,爬轻链 sum += Qsm(1, pos[htp[a]], pos[a]); a = fa[htp[a]]; } return sum += Qsm(1, pos[b], pos[a]);}inline int Mx(int a, int b) { int Mx = -0x3f3f3f3f; while(htp[a] != htp[b]) { Mx = Max(Mx, Qmx(1, pos[htp[a]], pos[a])); a = fa[htp[a]]; } Mx = Max(Qmx(1, pos[b], pos[a]), Mx); return Mx;}/*************** 轻重链剖分 ***************/void dfs1(int u) { sz[u] = 1; for(node *p = Adj[u]; p; p = p->nxt) { if(sz[p->v]) continue; fa[p->v] = u; dep[p->v] = dep[u]+1; dfs1(p->v); if(sz[hsn[u]] < sz[p->v]) hsn[u] = p->v; sz[u] += sz[p->v]; }}void dfs2(int u, int tp) { pos[u] = ++ dcnt; htp[u] = tp; rev[dcnt] = u; //pos记录了u的dfs序。 if(!hsn[u]) return; dfs2(hsn[u], tp); for(node *p = Adj[u]; p; p = p->nxt) if(htp[p->v]) continue; else if(p->v != hsn[u]) dfs2(p->v, p->v);}/******************************************/int main() { GET(n); int u, v; for(int i = 1; i < n; ++ i) { GET(u); GET(v); Add(u, v); Add(v, u); } for(int i = 1; i <= n; ++ i) GET(a[i]); dfs1(1); dfs2(1, 1); Build(1, 1, n); GET(q); char s[6]; for(int i = 1; i <= q; ++ i) { scanf("%s", s); GET(u); GET(v); if(s[0] == 'C') { a[u] = v; Ins(pos[u], v); } else { int t = LCA(u, v); if(s[1] == 'M') printf("%d\n", Max(Mx(u, t), Mx(v, t))); else printf("%d\n", sum(u, t) + sum(v, t) - a[t]); } } return 0;}
0 0
- BZOJ1036 [ZJOI2008]树的统计Count 树链剖分
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
- 【bzoj1036】【树链剖分】【ZJOI2008】树的统计Count
- 【BZOJ1036】【ZJOI2008】【树的统计count】【树链剖分】
- BZOJ1036: [ZJOI2008]树的统计Count (树链剖分)
- bzoj1036: [ZJOI2008]树的统计Count - 树链剖分
- 【树链剖分】[BZOJ1036][ZJOI2008]树的统计Count
- [树链剖分] BZOJ1036: [ZJOI2008]树的统计Count
- [bzoj1036][ZJOI2008]树的统计Count 树链剖分
- 【bzoj1036】【树链剖分】 [ZJOI2008]树的统计Count
- [Bzoj1036][ZJOI2008]树的统计Count
- 【BZOJ1036】【ZJOI2008】树的统计Count 树链剖分裸题
- 【ZJOI2008】【BZOJ1036】树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count && LCT
- bzoj1036: [ZJOI2008]树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count
- bzoj1036: [ZJOI2008]树的统计Count
- BZOJ1036: [ZJOI2008]树的统计Count
- JAVA语法基础之标识符和关键字
- 剑指Offer-28-字符串排列
- 深入研究java.lang.ThreadLocal类
- Rxlifecycle使用详解
- Java反射探索研究
- BZOJ1036: [ZJOI2008]树的统计Count (树链剖分)
- Android(13)java中的线程回顾,Android线程,主线程(UI线程)
- 【打造Ruby on Rails全栈工程师系列01】Ruby on Rails Mac用户环境设置安装
- 字符串匹配的KMP算法
- SQL函数学习----over函数
- C# 类成员类型 访问级别
- 20151115linux 下这么去搜文件? ( which,whereis,locate, find )使用!
- CSS选择器总结(代码实例+执行效果图)
- UVa 10712 - Count the Numbers