AtCoder Regular Contest 052 B - 円錐

問題
http://arc052.contest.atcoder.jp/tasks/arc052_b

3次元空間上にN個の円錐が互いに重なり合わないように存在する。
それぞれの円錐はYZ平面に垂直に浮かんでいる。
M個の区間のクエリ(L[i], R[i])が与えられる。
各クエリに対して、2平面X = L[i], X = R[i]で囲まれる空間と円錐との共有部分の体積を求めよ。


解法
O(NQ)解法
各クエリに対して、N個の円錐の体積を足し合わせる。
X = L[i]以上で切った円錐の体積を足す。
X = R[i]で切れる体積は切れた上部を引く。
半径R[i]の円錐の高さH[i]を、円錐の切った上部の体積の計算は、
長さの比率の3乗は体積の比率になることから、高さの比率を3乗して元の円錐の体積に掛けると良い。

ll X[111], R[111], H[111];
double V[111];
 
double calc(int i, ll from) {
  const double h = X[i] + H[i] - from;
  const double ratio = h / H[i];
  return V[i] * ratio * ratio * ratio;  // 体積比
};
 
int main() {
  int N, Q; cin >> N >> Q;
  rep(i, N) cin >> X[i] >> R[i] >> H[i];
  rep(i, N) V[i] = acos(-1) * R[i] * R[i] * H[i] / 3.0;
 
  while(Q--) {
    ll L, R; cin >> L >> R;
    double res = 0.0;
    rep(i, N) {
      if(L <= X[i] + H[i]) res += calc(i, max(L, X[i]));
      if(R <= X[i] + H[i]) res -= calc(i, max(R, X[i]));
    }
    printf("%.10f\n", res);
  }
  return 0;
}