社区讨论

为什么跑的这么慢?

P4074[WC2013] 糖果公园参与者 1已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mjnnqoev
此快照首次捕获于
2025/12/27 10:04
2 个月前
此快照最后确认于
2025/12/28 21:00
2 个月前
查看原帖
写的是括号序树上莫队,但为什么跑这么慢?
以及为什么块长要调到25000才能过,别的块长过不了,按理来说带修莫队块长不是 n2/3n^{2/3} 最优吗?LCA用的最弱的倍增,但复杂度瓶颈应该不在这吧。
CPP
#include<bits/stdc++.h>
// #define int long long
#define pb emplace_back
#define pii pair <int, int>
#define root 1, 1, n
#define id(p) (((p) + B - 1) / B)
#define R(id) ((id) * B)
#define L(id) ((id) * B - B + 1)
inline int read() {
	int x=0,f=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return x*f;
}
using namespace std;
const int N = 2e5 + 5, K = 20;
int n, m, q, a[N * 2], B, nl = 1, nr = 0, nt = 0;
long long res = 0, ans[N];
int v[N], w[N], c[N], ldfn[N], rdfn[N], ar, cnt[N], vis[N], f[N][K], d[N];
vector <int> edge[N];
struct Q{
  int l, r, t, addi, id;
}qa[N], op[N];
inline void add(const int& p){
  if (!vis[a[p]]){
    vis[a[p]] = 1;
    res += 1ll * w[++ cnt[c[a[p]]]] * v[c[a[p]]];
  }else{
    vis[a[p]] = 0;
    res -= 1ll * w[cnt[c[a[p]]] --] * v[c[a[p]]];
  }
}
inline void del(const int& p){
  if (!vis[a[p]]){
    vis[a[p]] = 1;
    res += 1ll * w[++ cnt[c[a[p]]]] * v[c[a[p]]];
  }else{
    vis[a[p]] = 0;
    res -= 1ll * w[cnt[c[a[p]]] --] * v[c[a[p]]];
  }
}
inline void update(const int& t){
  int p = op[t].id;
  if (ldfn[p] >= nl && ldfn[p] <= nr) del(ldfn[p]);
  if (rdfn[p] >= nl && rdfn[p] <= nr) del(rdfn[p]);
  swap(op[t].t, c[p]);
  if (ldfn[p] >= nl && ldfn[p] <= nr) add(ldfn[p]);
  if (rdfn[p] >= nl && rdfn[p] <= nr) add(rdfn[p]);
}
inline void dfs(const int& p, const int& fa){
  f[p][0] = fa;
  d[p] = d[fa] + 1;
  for (int i = 1; i < K; i ++) f[p][i] = f[f[p][i - 1]][i - 1];
  a[++ ar] = p;
  ldfn[p] = ar;
  for (auto to : edge[p]) if (to != fa){
    dfs(to, p);
  }
  a[++ ar] = p;
  rdfn[p] = ar;
}
int LCA(int a, int b){
  if (d[a] < d[b]) swap(a, b);
  for (int k = K - 1; k >= 0; k --)
    if (d[f[a][k]] >= d[b])
      a = f[a][k];
  if (a == b) return a;
  for (int k = K - 1; k >= 0; k --)
    if (f[a][k] != f[b][k])
      a = f[a][k], b = f[b][k];
  return f[a][0];
}
signed main(){
  // cin.tie(0)->sync_with_stdio(0);
  n = read(), m = read(), q = read();
  B = 25000;
  for (int i = 1; i <= m; i ++) v[i] = read();
  for (int i = 1; i <= n; i ++) w[i] = read();
  for (int i = 1; i < n; i ++){
    int u, v;
    u = read(), v = read();
    edge[u].pb(v);
    edge[v].pb(u);
  }
  for (int i = 1; i <= n; i ++) c[i] = read();
  int t = 0;
  dfs(1, 0);
  for (int i = 1; i <= q; i ++){
    int c;
    c = read();
    if (c){
      int &l = qa[i - t].l, &r = qa[i - t].r;
      l = read(), r = read();qa[i - t].id = i - t, qa[i - t].t = t;
      if (ldfn[l] > ldfn[r]) swap(l, r);
      int lca = LCA(l, r), flag = 0;
      if (lca == l) l = ldfn[l], r = ldfn[r];
      else l = rdfn[l], r = ldfn[r], qa[i - t].addi = lca;
    }else{
      t ++;
      op[t].id = read(), op[t].t = read();
    }
  }
  sort(qa + 1, qa + 1 + q - t, [](Q a, Q b){
    return id(a.l) == id(b.l) && id(a.r) == id(b.r) ? 
    a.t < b.t : (a.l == b.l ? a.r < b.r : a.l < b.l);
  });
  for (int i = 1; i <= q - t; i ++){
    auto [l, r, t, lca, ID] = qa[i];
    while (nl > l) add(-- nl);
    while (nr < r) add(++ nr);
    while (nl < l) del(nl ++);
    while (nr > r) del(nr --);
    while (nt < t) update(++ nt);
    while (nt > t) update(nt --);
    if (lca) add(ldfn[lca]);
    ans[ID] = res;
    if (lca) del(ldfn[lca]);
  }
  for (int i = 1; i <= q - t; i ++){
    cout << ans[i] << '\n';
  }
	return 0;
}

回复

1 条回复,欢迎继续交流。

正在加载回复...