Twlight!
2024-11-18 14:13:42
这题怎么写啊,我复杂度还标错了,还有 Day2 T2 好难。
给定
你需要支持
其中
显然,不能到达关键点
此时每个关键点连到的连通块里的所有点都可以到达该关键点,查询的时候只需要关心关键点周围的若干个连通块即可。
我们先考虑两种不同的暴力:
两种做法都可以被菊花图卡掉,不过这样已经有
不过我们可以发现,第一种做法在领域数较小的普通点适用,第二种做法在领域数较小的关键点适用,因此考虑对度数根号分治。
记缩点后的点数、边数分别为
这样一来,修改时对于度数不超过
注意些细节问题和写法,时间复杂度
写的很丑,请见谅。
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define int ll
const int N = 500000 + 10;
const int inf = 998244353;
using namespace std;
int read () {
int x = 0, k = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') k = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return (1ll * x * k);
}
int n, m, q;
int nn, bm;
int op, u, v;
int tp[N], a[N], b[N];
int col[N], dep[N];
vector<int> G[N], g[N];
unordered_set<int> H[N];
void bfs (int o) {
static queue<int> Q;
while (!Q.empty()) Q.pop();
if (tp[o]) return b[o] += a[o], col[o] = o, void();
Q.push(o); while (!Q.empty()) {
int u = Q.front(); Q.pop();
if (col[u]) continue; col[u] = o, b[o] += a[u];
for (int v: G[u]) if (!col[v] && !tp[v]) Q.push(v);
}
}
signed main() {
n = read(), m = read();
for (int i = 1; i <= n; ++i) tp[i] = read();
for (int i = 1; i <= n; ++i) a[i] = read();
for (int i = 1; i <= m; ++i) u = read(), v = read(), G[u].push_back(v), G[v].push_back(u);
for (int i = 1; i <= n; ++i) if (!col[i]) bfs(i);
for (int i = 1; i <= n; ++i) for (int v: G[i]) if (col[i] != col[v] && tp[i] + tp[v] != 2) H[col[i]].insert(col[v]), H[col[v]].insert(col[i]);
for (int i = 1; i <= n; ++i) nn += (dep[i] = H[i].size()); bm = sqrt(nn);
for (int i = 1; i <= n; ++i) if (tp[i]) for (int v: H[i]) (dep[v] <= bm) ? (b[i] += b[v]) : (g[i].push_back(v), 0);
q = read();
for (int i = 1; i <= q; ++i) {
op = read(), u = read(), v = (op == 1) ? read() : 0;
if (op == 1) {
if (dep[col[u]] <= bm) for (int o: H[col[u]]) if (tp[o]) b[o] += v - a[u];
b[col[u]] += v - a[u], a[u] = v;
} else {
int ret = b[u]; for (int o: g[u]) ret += b[o];
cout << ret << endl;
}
}
return 0;
}