【bzoj1036】[ZJOI2008]树的统计Count

xiaoxiao2021-02-28  118

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec   Memory Limit: 162 MB Submit: 16744   Solved: 6801 [ 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

Sample Output

4 1 2 2 10 6 5 6 5 16

HINT

Source

[ Submit][ Status][ Discuss]



树剖模板。。

这个鬼题首先要把这个点权转化为边权

这里蒟蒻将点o的权值转化为点o父边的权值

每次查询完后,要记得加上LCA的点权(不然会漏判)

还是调了有点久的。。

一个WA点:

如果是按照我的做法的话,一定要记得在修改时判一下存不存在父边(蒟蒻就是这样挂的)

#include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; const int maxn = 60100; const int seg_maxn = 240100; const int INF = 2147483647; struct data{ int w,from,to; }; vector<int> G[maxn]; data e[maxn]; int a[maxn]; int siz[maxn],wedge[maxn],top[maxn],faedge[maxn],fa[maxn],dep[maxn],son[maxn],sonw[maxn]; //树剖相关 int maxx[seg_maxn],sum[seg_maxn]; //线段树相关 int tot,n,tot_e; char s[40]; inline void maintain(int o) { int lc = o * 2,rc = o * 2 + 1; maxx[o] = max(maxx[lc],maxx[rc]); sum[o] = sum[lc] + sum[rc]; } inline int qsum(int o,int l,int r,int al,int ar) { if (al <= l && r <= ar) return sum[o]; int mid = l + r >> 1,lc = o * 2,rc = o * 2 + 1; if (ar <= mid) return qsum(lc,l,mid,al,ar); if (al >= mid + 1) return qsum(rc,mid + 1,r,al,ar); return qsum(lc,l,mid,al,ar) + qsum(rc,mid + 1,r,al,ar); } inline int qmax(int o,int l,int r,int al,int ar) { if (al <= l && r <= ar) return maxx[o]; int mid = l + r >> 1,lc = o * 2,rc = o * 2 + 1; if (ar <= mid) return qmax(lc,l,mid,al,ar); if (al >= mid + 1) return qmax(rc,mid + 1,r,al,ar); return max(qmax(lc,l,mid,al,ar),qmax(rc,mid + 1,r,al,ar)); } inline void update(int o,int l,int r,int P,int x) { if (l == r) { maxx[o] = x; sum[o] = x; return; } int mid = l + r >> 1,lc = o * 2,rc = o * 2 + 1; if (P <= mid) update(lc,l,mid,P,x); if (P >= mid + 1) update(rc,mid + 1,r,P,x); maintain(o); } inline void build(int o,int l,int r) { if (l == r) { maxx[o] = wedge[l]; sum[o] = wedge[l]; return; } int mid = l + r >> 1; int lc = o * 2,rc = o * 2 + 1; build(lc,l,mid); build(rc,mid + 1,r); maintain(o); } inline void init(int o,int f,int depth) { fa[o] = f; dep[o] = depth; siz[o] = 1; for (int i = 0; i < G[o].size(); i++) { int v = e[G[o][i]].to; if (v == f) continue; e[G[o][i]].w = a[v]; init(v,o,depth + 1); siz[o] += siz[v]; if (siz[son[o]] < siz[v]) { son[o] = v; sonw[o] = e[G[o][i]].w; } } } inline void cut(int o,int f) { if (G[o].size() == 1 && e[G[o][0]].to == f) return; int maxx = -INF,id = son[o]; faedge[id] = ++tot; wedge[tot] = sonw[o]; top[id] = top[o]; cut(id,o); for (int i = 0; i < G[o].size(); i++) { int v = e[G[o][i]].to; if (v == f || v == id) continue; top[v] = v; faedge[v] = ++tot; wedge[tot] = e[G[o][i]].w; cut(v,o); } } inline void change(int u,int x) { a[u] = x; int id = faedge[u]; if (!id) return; update(1,1,tot,id,x); } inline void swap(int& x,int& y) { int tmp = x; x = y; y = tmp; } inline int query_sum(int u,int v) { int f1 = top[u],f2 = top[v],ans = 0; while (f1 != f2) { if (dep[f1] < dep[f2]) {swap(f1,f2); swap(u,v);} ans += qsum(1,1,tot,faedge[f1],faedge[u]); u = fa[f1]; f1 = top[u]; } if (u == v) return ans + a[u]; if (dep[u] > dep[v]) swap(u,v); return ans + qsum(1,1,tot,faedge[son[u]],faedge[v]) + a[u]; } inline int query_max(int u,int v) { int f1 = top[u],f2 = top[v],ans = -INF; while (f1 != f2) { if (dep[f1] < dep[f2]) {swap(f1,f2); swap(u,v);} ans = max(ans,qmax(1,1,tot,faedge[f1],faedge[u])); u = fa[f1]; f1 = top[u]; } if (u == v) return max(ans,a[u]); if (dep[u] > dep[v]) swap(u,v); return max(max(ans,qmax(1,1,tot,faedge[son[u]],faedge[v])),a[u]); } inline int getint() { int ret = 0,f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') ret = ret * 10 + c - '0',c = getchar(); return ret * f; } int main() { n = getint(); for (int i = 1; i <= n - 1; i++) { int u = getint(),v = getint(); e[++tot_e] = (data){0,u,v}; G[u].push_back(tot_e); e[++tot_e] = (data){0,v,u}; G[v].push_back(tot_e); } for (int i = 1; i <= n; i++) a[i] = getint(); init(1,0,1); top[1] = 1; cut(1,0); build(1,1,tot); int q = getint(); for (int i = 1; i <= q; i++) { scanf("%s",s); if (!strcmp(s,"QMAX")) { int u = getint(),v = getint(); printf("%d\n",query_max(u,v)); } if (!strcmp(s,"QSUM")) { int u = getint(),v = getint(); printf("%d\n",query_sum(u,v)); } if (!strcmp(s,"CHANGE")) { int u = getint(),x = getint(); change(u,x); } } return 0; }

转载请注明原文地址: https://www.6miu.com/read-33794.html

最新回复(0)