260905D 旋转齿轮 gears
SS260905D. 旋转齿轮 gears
upd:
可能假了😭,考虑一个菊花,多次操作中心会让复杂度退化至 \(\mathcal O(n^2)\)。
暂时没有想到什么好的补救方法,但是出题人并没有卡以至于能拿最优解。。。
提供一个(可能)比较简单而且没发现有人写的做法,常数不大(?
题意即,动态激活点。每次给出点 \(x\) 和权值 \(w\),对于 \(x\) 位于的被激活的点构成的连通块中的每个点 \(y\),将 \(y\) 的权值加上 \((-1)^dw\),其中 \(d\) 是 \(x\) 到 \(y\) 的距离。
维护连通性不妨线段树分治+可撤销并查集,即可回答所有询问。
对于最后一个答案,并查集上维护子树加 tag 以及 tag 从父亲转移时是否需要乘 \(-1\) 即可,详情查看代码。
#include <algorithm>
#include <iostream>
const int N = 1e5 + 7;
typedef long long i64;
struct _dsu {
i64 add[N]; int coef[N]; // 上文提到的两个量
int fa[N], siz[N];
struct node { int u, v; } opt[N]; int top;
int find(int x) { return fa[x] == x ? x : find(fa[x]); }
int gco(int x) { return fa[x] == x ? 1 : coef[x] * gco(fa[x]); }
inline int clock() { return top; }
inline void merge(int x, int y) {
int a = gco(x), b = gco(y);
x = find(x), y = find(y);
if(x == y) return ;
if(siz[x] > siz[y]) std::swap(x, y);
coef[x] = a * b * -1, fa[x] = y, add[x] -= coef[x] * add[y], siz[y] += siz[x];
opt[++top] = {y, x};
}
void undo() {
auto& [y, x] = opt[top--];
fa[x] = x, add[x] += add[y] * coef[x], coef[x] = 1, siz[y] -= siz[x];
}
} T;
struct node {
int l, r;
std::basic_string<int> pt;
} tr[N*4];
#define self tr[rt]
#define rs (rt<<1|1)
#define ls (rt<<1)
void build(int l, int r, int rt=1) {
self.l = l, self.r = r;
if(l < r) {
int mid = (l + r) >> 1;
build(l, mid, ls), build(mid+1, r, rs);
}
}
void modify(int x, int y, int v, int rt=1) {
if(self.r < x || self.l > y) return ;
if(x <= self.l and self.r <= y) { self.pt += v; return ; }
return modify(x, y, v, ls), modify(x, y, v, rs);
}
std::basic_string<int> g[N], gt[N];
int delt[N], qry[N];
int vis[N], ans[N];
void dfs(int rt) {
int now = T.clock();
for(auto& p: self.pt) {
vis[p] = 1;
for(auto& v: g[p]) if(vis[v]) T.merge(p, v);
}
if(self.l < self.r) dfs(ls), dfs(rs);
else {
int x = self.l, y = T.find(qry[x]);
ans[x] = delt[x] * T.siz[y];
T.add[y] += T.gco(qry[x]) * delt[x];
}
for(auto& p: self.pt) vis[p] = 0;
while(T.clock() > now) T.undo();
}
int main() {
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int n; std::cin >> n;
for(int x, y, t = n; --t; ) std::cin >> x >> y, g[x] += y, g[y] += x;
int q, m = 1; std::cin >> q;
for(int i = 1; i <= q; ++i) {
int op, x; std::cin >> op >> x;
if(op == 3) qry[m] = x, std::cin >> delt[m++];
else gt[x] += m;
}
// 建树
build(1, --m);
for(int i = 1; i <= n; ++i) {
int las = 1, state = 0;
for(auto& p: gt[i]) {
if(state) las = p;
else if(p > las) modify(las, p-1, i);
state ^= 1;
}
if(!state && las <= m) modify(las, m, i);
}
// work
for(int i = 1; i <= n; ++i) T.fa[i] = i, T.siz[i] = T.coef[i] = 1;
dfs(1); i64 sum = 0;
for(int i = 1; i <= m; ++i) std::cout << ans[i] << "\n";
for(int i = 1; i <= n; ++i) sum += (T.add[i] % 360 + 360) % 360;
std::cout << sum << "\n";
}
本文来自博客园,作者:CuteNess,转载请注明原文链接:https://www.cnblogs.com/CuteNess/p/22870502

浙公网安备 33010602011771号