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";
}
posted @ 2026-09-07 11:01  CuteNess  阅读(5)  评论(0)    收藏  举报