博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 5957 Query on a graph
阅读量:5324 次
发布时间:2019-06-14

本文共 6522 字,大约阅读时间需要 21 分钟。

HDU 5957 Query on a graph

2016ACM/ICPC亚洲区沈阳站

题意

  • \(N(N \le 10^5)\)个点,\(N\)条边的连通图。
  • \(M \le 10^5\)操作:
  1. \(MODIFY\ u\ k\ d,k \le 2\):距离点\(u\)不超过\(k\)的点的权值都加上\(d\)
  2. \(QUERY\ u\ k\):询问距离\(d\)不超过\(k\)的点权和。

思路

  • 图的形状时一个环和若干树枝构成。
  • 考虑\(k=1\)时,分两种情况讨论:
  1. \(u\)在环上,则需要累加环上相邻两点权值,以及树枝上深度为1的所有点的权值,并且这些点的bfs序是连续的,那么显然可以用线段树维护权值和。
  2. \(u\)不在环上时,累加父亲节点的权值以及树枝深度为1的点权。
  • \(Q1(u)\)表示距离\(u\)不超过1的权值和。
  • \(k=2\)时,树枝上距离为2的点的bfs序也是连续的,所以同样用线段树维护,若\(u\)不在环上,累加上\(Q1(f_u)-w_u\)即可;若\(u\)在环上,求出\(Q1(v_1)+Q1(v_2)-2w_u\)\(v_1、v_2\)表示换上与\(u\)相邻的点,显然\(u\)被重复计数两次。
  • 当环的长度分别为3、4时,\(Q1(v_1)、Q2(v_2)\)存在交集,需要扣除重复计数的值。
#include
using namespace std;typedef long long ll;typedef unsigned long long ul;#define sz(x) ((int)(x).size())#define rep(i,l,r) for(int i=(l),I=(r);i
> 1; sum[ls] += add[t] * (m - l + 1), add[ls] += add[t]; sum[rs] += add[t] * (r - m), add[rs] += add[t]; add[t] = 0; }}void build(int t, int l, int r) { sum[t] = add[t] = 0; if (l < r) { int m = (l + r) >> 1; build(ls, l, m), build(rs, m + 1, r); }}inline void upd(int t, int l, int r, int L, int R, ll v) { if (R < l || r < L || L > R) return ; if (L <= l && r <= R) { sum[t] += (r - l + 1) * v, add[t] += v; return ; } down(t, l, r); int m = (l + r) >> 1; upd(ls, l, m, L, R, v), upd(rs, m + 1, r, L, R, v); up(t);}inline ll qry(int t, int l, int r, int L, int R) { if (R < l || r < L || L > R) return 0; if (L <= l && r <= R) return sum[t]; down(t, l, r); int m = (l + r) >> 1; ll ret = qry(ls, l, m, L, R) + qry(rs, m + 1, r, L, R); up(t); return ret;}int n, q, tot, f[N], pos[N], deg[N], L[N][3], R[N][3];vector
cir, e[N];void bfs() { queue
que; rep(i, 1, n + 1) if (deg[i] == 1) que.push(i); while (!que.empty()) { int u = que.front(); que.pop(); rep(i, 0, sz(e[u])) { int v = e[u][i]; --deg[v]; if (deg[v] == 1) que.push(v); } } rep(i, 1, n + 1) deg[i] = (deg[i] == 2); cir.clear(); rep(i, 1, n + 1) if (deg[i]) { int u = i; do { rep(j, 0, sz(e[u])) { int v = e[u][j]; if (deg[v] && (cir.empty() || v != cir.back())) { pos[u] = sz(cir); cir.push_back(u); u = v; break; } } } while (u != i); break; }}int que[N];void BFS(int s) { int h = 0, t = 0; que[t++] = s, f[s] = -1; while (h < t) { int u = que[h++]; L[u][0] = R[u][0] = ++tot; L[u][1] = L[u][2] = n + 1, R[u][1] = R[u][2] = 0; rep(i, 0, sz(e[u])) { int v = e[u][i]; if (v == f[u] || deg[v]) continue; f[v] = u, que[t++] = v; } } for (int i = t - 1; i > 0; --i) { int v = que[i]; int u = f[v]; L[u][1] = min(L[u][1], L[v][0]), R[u][1] = max(R[u][1], R[v][0]); u = f[u]; if (u == -1) continue; L[u][2] = min(L[u][2], L[v][0]), R[u][2] = max(R[u][2], R[v][0]); } // printf("u = %d, ", u); // rep(i, 0, 3) printf("(%d, %d) ", L[u][i], R[u][i]);puts("");}char op[20];inline ll Q0(int u) { return qry(1, 0, tot, L[u][0], R[u][0]);}inline ll Q1(int u) { ll ans = Q0(u) + qry(1, 0, tot, L[u][1], R[u][1]); if (deg[u]) { ans += Q0(cir[(pos[u] + 1) % sz(cir)]); ans += Q0(cir[(pos[u] - 1 + sz(cir)) % sz(cir)]); } else { ans += Q0(f[u]); } return ans;}inline void A0(int u, ll v) { upd(1, 0, tot, L[u][0], R[u][0], v);}inline void A1(int u, ll v) { A0(u, v), upd(1, 0, tot, L[u][1], R[u][1], v); if (deg[u]) { A0(cir[(pos[u] + 1) % sz(cir)], v); A0(cir[(pos[u] - 1 + sz(cir)) % sz(cir)], v); } else { A0(f[u], v); }}int main() { int T; scanf("%d", &T); rep(cas, 0, T) { scanf("%d", &n); rep(i, 1, n + 1) deg[i] = 0, e[i].clear(); rep(i, 0, n) { int u, v; scanf("%d%d", &u, &v); ++deg[u], ++deg[v]; e[u].push_back(v), e[v].push_back(u); } bfs(); tot = 0; rep(i, 1, n + 1) if (deg[i]) BFS(i); build(1, 0, tot); scanf("%d", &q); rep(_q, 0, q) { scanf(" %s", op); if (op[0] == 'M') { int u, k, d; scanf("%d%d%d", &u, &k, &d); if (k == 0) { A0(u, d); } else if (k == 1) { A1(u, d); } else if (k == 2) { A0(u, d), upd(1, 0, tot, L[u][1], R[u][1], d), upd(1, 0, tot, L[u][2], R[u][2], d); if (deg[u]) { int v1 = cir[(pos[u] + 1) % sz(cir)]; int v2 = cir[(pos[u] - 1 + sz(cir)) % sz(cir)]; A1(v1, d), A1(v2, d), A0(u, -2 * d); if (sz(cir) == 3) { A0(v1, -d), A0(v2, -d); } else if (sz(cir) == 4) { A0(cir[(pos[u] + 2) % sz(cir)], -d); } } else { A1(f[u], d), A0(u, -d); } } } else { int u, k; scanf("%d%d", &u, &k); ll ans = 0; if (k == 0) { ans = Q0(u); } else if (k == 1) { ans = Q1(u); } else if(k == 2) { ans = Q0(u) + qry(1, 0, tot, L[u][1], R[u][1]) + qry(1, 0, tot, L[u][2], R[u][2]); if (deg[u]) { int v1 = cir[(pos[u] + 1) % sz(cir)]; int v2 = cir[(pos[u] - 1 + sz(cir)) % sz(cir)]; ans += Q1(v1) + Q1(v2) - 2ll * Q0(u); if (sz(cir) == 3) { ans -= Q0(v1) + Q0(v2); } else if (sz(cir) == 4) { ans -= Q0(cir[(pos[u] + 2) % sz(cir)]); } } else { ans += Q1(f[u]) - Q0(u); } } printf("%lld\n", ans); } } } return 0;}

转载于:https://www.cnblogs.com/mcginn/p/6028504.html

你可能感兴趣的文章
like tp
查看>>
posix多线程有感--线程高级编程(线程属性函数总结)(代码)
查看>>
spring-使用MyEcilpse创建demo
查看>>
DCDC(4.5V to 23V -3.3V)
查看>>
kettle导数到user_用于left join_20160928
查看>>
activity 保存数据
查看>>
typescript深copy和浅copy
查看>>
linux下的静态库与动态库详解
查看>>
hbuilder调底层运用,多张图片上传
查看>>
深入理解基于selenium的二次开发
查看>>
较快的maven的settings.xml文件
查看>>
Git之初体验 持续更新
查看>>
Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException
查看>>
随手练——HDU 5015 矩阵快速幂
查看>>
启动redis一闪就关
查看>>
Maven之setting.xml配置文件详解
查看>>
ASP.NET 4.5 Web Forms and Visual Studio vs2013年入门1
查看>>
SDK目录结构
查看>>
malloc() & free()
查看>>
HDU 2063 过山车
查看>>