Is segment tree N*log(n) solution too slow or there is better implementation
Main idea is to split cube into 8 parts and query/add for each one.
Here is my code that have TL6.
Any ideas of how to improve it?
import java.io.*;
public class P1470 {
static int [] tree = new int[10000000];
private static int n;
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(new OutputStreamWriter(System.out));
n = Integer.valueOf(reader.readLine());
while (true) {
String line = reader.readLine();
if (line.startsWith("1")) {
add(new Ufo(line));
} else if (line.startsWith("2")){
writer.println(query(new Region(line)));
} else {
break;
}
}
writer.flush();
}
private static int query(Region region) {
return doQuery(region, new Region(0, 0, 0, n - 1, n - 1, n - 1), 0);
}
private static int doQuery(Region q, Region r, int node) {
if (!r.overlaps(q)) return 0;
if (q.contains(r)) {
return tree[node];
}
int xMid = (r.x1 + r.x2) / 2;
int yMid = (r.y1 + r.y2) / 2;
int zMid = (r.z1 + r.z2) / 2;
return
doQuery(q, new Region(r.x1, r.y1, r.z1, xMid, yMid, zMid), node * 8 + 1) +
doQuery(q, new Region(xMid + 1, r.y1, r.z1, r.x2, yMid, zMid), node * 8 + 2) +
doQuery(q, new Region(xMid + 1, r.y1, zMid + 1, r.x2, yMid, r.z2), node * 8 + 3) +
doQuery(q, new Region(r.x1, r.y1, zMid + 1, xMid, yMid, r.z2), node * 8 + 4) +
doQuery(q, new Region(r.x1, yMid + 1, r.z1, xMid, r.y2, zMid), node * 8 + 5) +
doQuery(q, new Region(xMid + 1, yMid + 1, r.z1, r.x2, r.y2, zMid), node * 8 + 6) +
doQuery(q, new Region(xMid + 1, yMid + 1, zMid + 1, r.x2, r.y2, r.z2), node * 8 + 7) +
doQuery(q, new Region(r.x1, yMid + 1, zMid + 1, xMid, r.y2, r.z2), node * 8 + 8);
}
private static void add(Ufo ufo) {
doAdd(ufo, new Region(0, 0, 0, n - 1, n - 1, n - 1), 0);
}
private static void doAdd(Ufo ufo, Region r, int node) {
if (!r.contains(ufo)) return;
tree[node] += ufo.count;
if (r.isPoint()) return;
int xMid = (r.x1 + r.x2) / 2;
int yMid = (r.y1 + r.y2) / 2;
int zMid = (r.z1 + r.z2) / 2;
doAdd(ufo, new Region(r.x1, r.y1, r.z1, xMid, yMid, zMid), node * 8 + 1);
doAdd(ufo, new Region(xMid + 1, r.y1, r.z1, r.x2, yMid, zMid), node * 8 + 2);
doAdd(ufo, new Region(xMid + 1, r.y1, zMid + 1, r.x2, yMid, r.z2), node * 8 + 3);
doAdd(ufo, new Region(r.x1, r.y1, zMid + 1, xMid, yMid, r.z2), node * 8 + 4);
doAdd(ufo, new Region(r.x1, yMid + 1, r.z1, xMid, r.y2, zMid), node * 8 + 5);
doAdd(ufo, new Region(xMid + 1, yMid + 1, r.z1, r.x2, r.y2, zMid), node * 8 + 6);
doAdd(ufo, new Region(xMid + 1, yMid + 1, zMid + 1, r.x2, r.y2, r.z2), node * 8 + 7);
doAdd(ufo, new Region(r.x1, yMid + 1, zMid + 1, xMid, r.y2, r.z2), node * 8 + 8);
}
static class Region {
int x1, y1, z1, x2, y2, z2;
Region(String s) {
String[] split = s.split("\\s");
x1 = Integer.valueOf(split[1]);
y1 = Integer.valueOf(split[2]);
z1 = Integer.valueOf(split[3]);
x2 = Integer.valueOf(split[4]);
y2 = Integer.valueOf(split[5]);
z2 = Integer.valueOf(split[6]);
}
Region(int x1, int y1, int z1, int x2, int y2, int z2) {
this.x1 = x1;
this.y1 = y1;
this.z1 = z1;
this.x2 = x2;
this.y2 = y2;
this.z2 = z2;
}
boolean contains(Ufo ufo) {
return ufo.x >= x1 && ufo.x <= x2 && ufo.y >= y1 && ufo.y <= y2 && ufo.z >= z1 && ufo.z <= z2;
}
boolean contains(Region r) {
return overlaps(r) && x1 <= r.x1 && x2 >= r.x2 && y1 <= r.y1 && y2 >= r.y2 && z1 <= r.z1 && z2 >= r.z2;
}
boolean overlaps(Region r) {
return r.x1 <= x2 && r.x2 >= x1 && r.y1 <= y2 && r.y2 >= y1 && r.z1 <= z2 && r.z2 >= z1;
}
boolean isPoint() {
return x1 == x2 && y1 == y2 && z1 == z2;
}
}
static class Ufo {
int x, y, z, count;
Ufo(String s) {
String[] split = s.split("\\s");
x = Integer.valueOf(split[1]);
y = Integer.valueOf(split[2]);
z = Integer.valueOf(split[3]);
count = Integer.valueOf(split[4]);
}
}
}