ENG  RUSTimus Online Judge
Online Judge
Problems
Authors
Online contests
About Online Judge
Frequently asked questions
Site news
Webboard
Links
Problem set
Submit solution
Judge status
Guide
Register
Update your info
Authors ranklist
Current contest
Scheduled contests
Past contests
Rules
back to board

Discussion of Problem 1470. UFOs

Is segment tree N*log(n) solution too slow or there is better implementation
Posted by Vitalii Arbuzov 23 Mar 2011 23:11
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]);
        }
    }
}

Re: Is segment tree N*log(n) solution too slow or there is better implementation
Posted by gaston770 21 Apr 2011 20:14
Hi, try searching for Fenwick Tree's in 3 Dimensions.
Re: Is segment tree N*log(n) solution too slow or there is better implementation
Posted by LaVuna [NULP] 24 Dec 2020 14:33
My solution using segment tree is accepted. Time : 0.796, Memory: 65 484 KB. I didn't use recursion and solution is very efficient. I used such idea https://codeforces.com/blog/entry/18051, but in 3D