結果

問題 No.235 めぐるはめぐる (5)
ユーザー 👑 hos.lyrichos.lyric
提出日時 2019-01-14 22:13:44
言語 D
(dmd 2.105.2)
結果
WA  
実行時間 -
コード長 5,895 bytes
コンパイル時間 983 ms
コンパイル使用メモリ 107,420 KB
実行使用メモリ 86,636 KB
最終ジャッジ日時 2023-09-03 22:06:36
合計ジャッジ時間 9,048 ms
ジャッジサーバーID
(参考情報)
judge13 / judge12
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 WA -
testcase_01 WA -
testcase_02 WA -
権限があれば一括ダウンロードができます

ソースコード

diff #

import std.conv, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.container, std.math, std.range, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken().to!int; }
long readLong() { return readToken().to!long; }
real readReal() { return readToken().to!real; }

void chmin(T)(ref T t, in T f) { if (t > f) t = f; }
void chmax(T)(ref T t, in T f) { if (t < f) t = f; }

int binarySearch(T)(in T[] as, in bool delegate(T) test) { int low = -1, upp = cast(int)(as.length); for (; low + 1 < upp; ) { int mid = (low + upp) >> 1; (test(as[mid]) ? low : upp) = mid; } return upp; }
int lowerBound(T)(in T[] as, in T val) { return as.binarySearch((T a) => (a < val)); }
int upperBound(T)(in T[] as, in T val) { return as.binarySearch((T a) => (a <= val)); }


immutable MO = 10L^^9 + 7;
immutable LIM_LOGN = 20;

class SegmentTree {
  int n;
  long[] coefSum;
  long[] sum, add;
  this(int n_, long[] ini, long[] coef) {
    for (n = 1; n < n_; n <<= 1) {}
    coefSum = new long[n + 1];
    foreach (i; 0 .. n_) {
      coefSum[i + 1] = (coefSum[i] + coef[i]) % MO;
    }
    coefSum[n_ + 1 .. $] = coefSum[n_];
    sum = new long[n << 1];
    add = new long[n << 1];
    foreach (i; 0 .. n_) {
      sum[n + i] = ini[i];
    }
    foreach_reverse (u; 1 .. n) {
      sum[u] = (sum[u << 1] + sum[u << 1 | 1]) % MO;
    }
  }
  long query(int u, int l, int r, int a, int b, long val) {
    chmax(a, l);
    chmin(b, r);
    if (a >= b) {
      return 0;
    }
debug{
// writefln("query %s [%s, %s); [%s, %s) %s",u,l,r,a,b,val);
}
    if (a == l && b == r) {
      (sum[u] += (coefSum[r] - coefSum[l]) * val) %= MO;
      (add[u] += val) %= MO;
      return sum[u];
    }
    const uL = u << 1;
    const uR = u << 1 | 1;
    const mid = (l + r) >> 1;
    (sum[uL] += (coefSum[mid] - coefSum[l]) * add[u]) %= MO;
    (add[uL] += add[u]) %= MO;
    (sum[uR] += (coefSum[r] - coefSum[mid]) * add[u]) %= MO;
    (add[uR] += add[u]) %= MO;
    add[u] = 0;
    const ret = (query(uL, l, mid, a, b, val) + query(uR, mid, r, a, b, val)) % MO;
    sum[u] = (sum[uL] + sum[uR]) % MO;
    return ret;
  }
  long query(int a, int b, long val) {
    return query(1, 0, n, a, b + 1, val);
  }
}

int N;
long[] S;
long[] C;
int[] A, B;
int Q;
int[] T, X, Y;
long[] Z;

int[][] graph;
int[][] par;
int[] dep;
int[] sz;

int E;
int[] F;
int[][] us;
int[] es, fs;

void dfs(int u, int p, int d) {
  par[0][u] = p;
  dep[u] = d;
  sz[u] = 1;
  foreach (v; graph[u]) {
    if (v != p) {
      dfs(v, u, d + 1);
      sz[u] += sz[v];
    }
  }
  bool found;
  foreach (v; graph[u]) {
    if (v != p) {
      if (2 * sz[v] >= sz[u]) {
        debug {
          writefln("heavy %s %s", u, v);
        }
        found = true;
        es[u] = es[v];
      }
    }
  }
  if (!found) {
    es[u] = E++;
    F ~= 0;
  }
  fs[u] = F[es[u]]++;
}

int getLCA(int u, int v) {
  foreach_reverse (j; 0 .. LIM_LOGN) {
    if (dep[u] - (1 << j) >= dep[v]) {
      u = par[j][u];
    }
    if (dep[v] - (1 << j) >= dep[u]) {
      v = par[j][v];
    }
  }
  foreach_reverse (j; 0 .. LIM_LOGN) {
    if (par[j][u] != par[j][v]) {
      u = par[j][u];
      v = par[j][v];
    }
  }
  if (u != v) {
    u = par[0][u];
  }
  return u;
}

void main() {
  try {
    for (; ; ) {
      N = readInt();
      S = new long[N];
      foreach (u; 0 .. N) {
        S[u] = readLong();
      }
      C = new long[N];
      foreach (u; 0 .. N) {
        C[u] = readLong();
      }
      A = new int[N - 1];
      B = new int[N - 1];
      foreach (i; 0 .. N - 1) {
        A[i] = readInt() - 1;
        B[i] = readInt() - 1;
      }
      Q = readInt();
      T = new int[Q];
      X = new int[Q];
      Y = new int[Q];
      Z = new long[Q];
      foreach (q; 0 .. Q) {
        T[q] = readInt();
        X[q] = readInt() - 1;
        Y[q] = readInt() - 1;
        if (T[q] == 0) {
          Z[q] = readLong();
        }
      }
      
      graph = new int[][N];
      foreach (i; 0 .. N - 1) {
        graph[A[i]] ~= B[i];
        graph[B[i]] ~= A[i];
      }
      par = new int[][](LIM_LOGN, N);
      dep = new int[N];
      sz = new int[N];
      E = 0;
      F = [];
      es = new int[N];
      fs = new int[N];
      dfs(0, 0, 0);
      foreach (j; 1 .. LIM_LOGN) {
        foreach (u; 0 .. N) {
          par[j][u] = par[j - 1][par[j - 1][u]];
        }
      }
      us = new int[][E];
      foreach (e; 0 .. E) {
        us[e] = new int[F[e]];
      }
      foreach (u; 0 .. N) {
        fs[u] = F[es[u]] - 1 - fs[u];
        us[es[u]][fs[u]] = u;
      }
      debug {
        writefln("E = %s", E);
        writefln("F = %s", F);
        writefln("es = %s", es);
        writefln("fs = %s", fs);
        writefln("us = %s", us);
      }
      auto segs = new SegmentTree[E];
      foreach (e; 0 .. E) {
        segs[e] = new SegmentTree(F[e], us[e].map!(u => S[u]).array, us[e].map!(u => C[u]).array);
      }
      
      long solve(int u, long val) {
        long ret;
        for (; ; ) {
debug{
// writeln("  ",es[u]," ",fs[u]," ",val);
}
          (ret += segs[es[u]].query(0, fs[u], val)) %= MO;
          u = us[es[u]][0];
          if (u == 0) {
            break;
          }
          u = par[0][u];
        }
        return ret;
      }
      
      foreach (q; 0 .. Q) {
        const l = getLCA(X[q], Y[q]);
        debug {
          writefln("X[q] = %s, Y[q] = %s: l = %s", X[q], Y[q], l);
        }
        long ans = (solve(X[q], +Z[q]) + solve(Y[q], +Z[q]) - solve(l, -Z[q])) % MO;
        ans = (ans % MO + MO) % MO;
        if (T[q] == 1) {
          writeln(ans);
        }
      }
    }
  } catch (EOFException e) {
  }
}
0