Mnzn 不理解

P3038 [USACO11DEC] Grass Planting G

Dream_Stars @ 2024-12-15 19:52:33

为什么 query 的时候要 -1 才能 AC?

我明明已经处理边权问题了啊(见注释)。

# include <bits/stdc++.h>

# define int long long
# define up(i ,x ,y) for (int i = x ; i <= y ; i ++)

using namespace std;

inline int read(){int s = 0 , w = 0;char c = getchar();while(!isdigit(c)){w |= (c == '-');c = getchar();}while(isdigit(c)){s = (s << 1) + (s << 3) + (c ^ 48);c = getchar();}return w ? -s : s;}
inline void write(int x){if(x < 0) putchar('-') , x = -x;if(x > 9) write(x / 10);putchar(x % 10 | 48);}
inline void writesp(int x){write(x) , putchar(' ');}
inline void writeln(int x){write(x) , putchar('\n');}

const int N = 1e5 + 10;
int n ,m, r ,a[N] ,deep[N] ,fa[N] ,sz[N] ,son[N] ,dfn[N] ,tp[N];
int tot ,w[N];

struct Edge {int to ,nxt ;} edge[N << 1] ; int cnt ,head[N];

inline void add (int u ,int v){
  edge[++ cnt] = {v ,head[u]} ;
  head[u] = cnt;
} inline void dfs1 (int u ,int fath){
  deep[u] = deep[fath] + 1, fa[u] = fath;
  sz[u] = 1;
  int mx = 0;
  for (int i = head[u] ; i ; i = edge[i].nxt){
    int v = edge[i].to;
    if (v == fath) continue;
    dfs1 (v ,u);
    a[v] = 1;
    sz[u] += sz[v];
    if (sz[v] > mx){
      mx = sz[v];
      son[u] = v;
    }
  }
} inline void dfs2 (int u ,int tops){
  tp[u] = tops ,dfn[u] = ++ tot;
  w[tot] = a[u];

  if (!son[u]) return;//叶节点。
  dfs2 (son[u] ,tops);

  for (int i = head[u] ; i ; i = edge[i].nxt){
    int v = edge[i].to;
    if (v == son[u] || v == fa[u]) continue;
    dfs2 (v ,v);
  }
} 

struct sgt {int l ,r ,sum ,lazy;}tr[N << 2];

# define lc u << 1
# define rc u << 1 | 1

inline void pushup (int u){
  tr[u].sum = (tr[lc].sum + tr[rc].sum);
} inline void pushdown (int u){
  if (tr[u].lazy){
    tr[lc].sum += (tr[lc].r - tr[lc].l + 1) * tr[u].lazy ,
    tr[rc].sum += (tr[rc].r - tr[rc].l + 1) * tr[u].lazy ;
    tr[lc].lazy += tr[u].lazy ,
    tr[rc].lazy += tr[u].lazy;
    tr[u].lazy = 0;
  }
} inline void build (int u ,int l ,int r){
  tr[u].l = l ,tr[u].r = r;
  if (l == r){
    tr[u].sum = w[l];
    return ;
  }
  int mid = ((l + r) >> 1);
  build (u << 1 ,l ,mid);
  build (u << 1 | 1 ,mid + 1 ,r);
  pushup (u);
} inline void update (int u ,int l ,int r ,int ql ,int qr ,int val){
  if (l >= ql && r <= qr){
    tr[u].sum += (tr[u].r - tr[u].l + 1) * val;
    tr[u].lazy += val;
    return ;
  }
  pushdown (u);
  int mid = ((l + r) >> 1);
  if (ql <= mid) update (u << 1 ,l ,mid ,ql ,qr ,val);
  if (mid < qr) update (u << 1 | 1 ,mid + 1, r ,ql ,qr ,val);
  pushup (u);
} inline int query (int u ,int l ,int r ,int ql ,int qr){
  if (l >= ql && r <= qr) return tr[u].sum;
  pushdown (u);
  int mid = ((l + r) >> 1) ,res = 0;
  if (ql <= mid) res += query (lc ,l ,mid ,ql ,qr);
  if (mid < qr) res += query (rc ,mid + 1, r ,ql ,qr);
  return res;
} inline void update_edge (int u ,int v ,int val){
  while (tp[u] ^ tp[v]){
    if (deep[tp[u]] < deep[tp[v]]) swap (u ,v);
    update (1 ,1 ,n ,dfn[tp[u]] ,dfn[u] ,val);
    u = fa[tp[u]];
  }
  if (deep[u] > deep[v]) swap (u ,v);
  update (1 ,1 ,n ,dfn[u] ,dfn[v] ,val);
  update (1 ,1 ,n ,dfn[u] ,dfn[u] ,-val);//1
} inline int query_edge (int u ,int v){
  int res = 0;
  while (tp[u] ^ tp[v]){
    if (deep[tp[u]] < deep[tp[v]]) swap (u ,v);
    res += query (1 ,1 ,n ,dfn[tp[u]] ,dfn[u]) ;
    u = fa[tp[u]];
  }
  if (deep[u] > deep[v]) swap (u ,v);
  res += query (1 ,1 ,n ,dfn[u] ,dfn[v]);
  res -= query (1 ,1 ,n ,dfn[u] ,dfn[u]);//2
  return res;
} signed main (){
  n = read () ,m = read ();
  r = 1;

  up (i ,1 ,n - 1){
    int u = read () ,v = read ();
    add (u ,v) ,add (v ,u);
  }

  dfs1 (r ,0);
  dfs2 (r ,0);

  build (1 ,1 ,n);

  while (m --){
    char op;
    cin >> op;
    if (op == 'P'){
      int x = read () ,y = read () ;
      update_edge (x ,y ,1);
    } if (op == 'Q'){
      int x = read () ,y = read ();
      writeln (query_edge (x ,y) - 1);
    }
  }
  return 0;
}

|