树链剖分(QTREE)

只敢说写过了这个题,下次能不能写过就靠运气了。


发现不是很难调,代码量也还好,只写了140+行,3665B,但速度奇慢,也许是常数太大。。


照例代码,各位神犇可以直接忽视我的缩行:

#include <stdio.h>
#include <memory.h>

#define maxn 10010
#define tail_zero(i) lgr[i]
#define oo 0x3F3F3F3F
#define base 16384
#define clr(a) memset (a, 0, sizeof (a))

typedef int arr[maxn];

int etop, htop, n;
arr da_data[17];
arr bfr, bto, pred, succ, hash, depth, lgr, cost, size, queue, edge, child;
int next[maxn << 1], point[maxn << 1];
int st[base << 1], *pnt = da_data[0], *da[17];

inline int max (int i, int j)
{
  return i > j ? i : j;
}

inline void adde (int s, int t, int w)
{
  point[++etop] = t;
  next[etop] = edge[s];
  edge[s] = etop;
  cost[etop >> 1] = w;
}

inline void st_modify (int i, int v)
{
  for (st[i += base] = v, i >>= 1; i; i >>= 1)
    st[i] = max (st[i << 1], st[i << 1 | 1]);
}

inline int st_query (int l, int r)
{
  if (l > r) return -oo;
  int ans = -oo;
  for (l += base - 1, r += base + 1; l ^ r ^ 1; l >>= 1, r >>= 1)
    {
      if (~l & 1) ans = max (st[l ^ 1], ans);
      if ( r & 1) ans = max (ans, st[r ^ 1]);
    }
  return ans;
}

inline int lca (int s, int t)
{
  int k;
  if (depth[s] > depth[t])
    k = s, s = t, t = k;
  for (; depth[s] != depth[t]; )
    t = da[tail_zero (depth[t] - depth[s])][t];
  if (s == t)
    return s;
  for (k = lgr[depth[s]] + 1; k >= 0; --k)
    if (da[k][s] != da[k][t])
      s = da[k][s], t = da[k][t];
  return pnt[s];
}

inline int query (int h, int l)
{
  int ans = -oo, t;
  while (bfr[h] != bfr[l])
    {
      ans = max (ans, st_query (hash[succ[bfr[l]]], hash[pred[l]]));
      ans = max (ans, cost[pred[bfr[l]]]);
      if ((t = point[pred[bfr[l]] << 1]) != bfr[l])
        l = t;
      else
        l = point[pred[bfr[l]] << 1 | 1];
    }
  if (pred[l])
    ans = max (ans, st_query (hash[succ[h]], hash[pred[l]]));
  return ans;
}

inline void init ()
{
  int i, e, head = 0, tail = 1, p;
  queue[1] = depth[1] = 1, htop = 0;
  for (; head != tail; )
    for (e = edge[i = queue[++head]]; e; e = next[e])
      if (!depth[p = point[e]])
        queue[++tail] = p, depth[p] = depth[i] + 1, pnt[p] = i, pred[p] = e >> 1;
  for (i = n; i; --i)
    {
      ++size[p = queue[i]];
      if (size[child[pnt[p]]] < size[p])
        child[pnt[p]] = p, succ[pnt[p]] = pred[p];
      size[pnt[p]] += size[p];
    }
  for (i = 1; i <= n; ++i)
    {
      for (e = 1, p = queue[i]; (1 << e) <= depth[p]; ++e)
        da[e][p] = da[e - 1][da[e - 1][p]];
      if (!hash[pred[p]])
        for (e = child[p]; e; e = child[e])
          hash[pred[e]] = ++htop, st_modify (htop, cost[pred[e]]);
      if (child[p])
        bfr[child[p]] = bfr[p], bto[bfr[p]] = child[p];
    }
}

inline void solve()
{
  clr (da_data), clr (bfr), clr (bto), clr (size), clr (hash), clr (depth), clr (edge), clr (succ), clr (pred), clr (child), clr (st);
  int i, a, b, c;
  char cmd[50];
  scanf ("%d", &n);
  for (etop = i = 1; i < n; ++i)
    scanf ("%d%d%d", &a, &b, &c), adde (a, b, c), adde (b, a, c);
  for (i = 1; i <= n; ++i)
    bfr[i] = bto[i] = i;
  init ();
  for (scanf ("%s", cmd); cmd[0] != 'D'; scanf ("%s", cmd))
    {
      scanf ("%d%d", &a, &b);
      if (cmd[0] == 'Q')
        i = lca (a, b), printf ("%d\n", max (query (i, a), query (i, b)));
      else if (hash[a])
        st_modify (hash[a], b);
      else
        cost[a] = b;
    }
}

int main ()
{
  freopen ("qtree.in" , "r", stdin);
  freopen ("qtree.out", "w", stdout);
  int t;
  for (t = 2; t <= maxn; ++t)
    lgr[t] = lgr[t - 1] + ((t & -t) == t);
  for (t = 0; t <= 16; ++t)
    da[t] = da_data[t];
  scanf ("%d", &t);
  for (; t; --t)
    solve ();
  
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值