Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

カーテン

もうすぐ夏がやってくる．あなたは夏に向けて部屋の模様替えをすることにした．今年の夏はとても日差しが強いことが予想されており，まぶしいのが苦手なあなたには辛い季節になりそうだ．そこで，あなたは部屋の明るさを調節するために，部屋の窓にカーテンを取り付けようと考えた．

取り付けるカーテンは長方形であり，辺が地面に対して垂直，もしくは平行であるように取り付ける．また，あなたの部屋の窓は非常に特殊な形をしており，各辺が地面に平行または垂直であるような N 角形で表される．そのため，カーテンを取り付けたときにカーテンに覆われていない窓の面積がどのくらいになるのかを求めるのは難しい．部屋の明るさを調節するためにも，カーテンを取り付ける位置を決めた時にどのくらい窓が覆えるかを知ることは重要である．そこで，あなたは窓とカーテンの設置位置と形状が与えられたときに，カーテンに覆われていない窓の面積を求めるプログラムを作ることにした．

例として次のような窓とカーテンの設置の仕方を考える．この場合はカーテンに隠れていない窓の面積は 8 となる．この例はサンプル入力の 3 ケース目に対応する．

Input

入力は複数データセットからなる．
各データセットは次の形式で与えられる．

N
x1 y1
:
:
xN yN
a1 b1
a2 b2
a3 b3
a4 b4

最初の行には窓の持つ頂点数を表す整数 N が与えられる (4 ≤ N ≤ 100)．続く N 行には窓の相異なる頂点のx座標を表す整数 xi とy座標を表す整数 yi が与えられる (-20,000 ≤ xi, yi ≤ 20,000, 1 ≤ i ≤ N)．ここで，y軸の正の向きはx軸の正の向きから90度分反時計回りに回転させた方向とする．さらに，続く 4 行にはカーテンの相異なる頂点のx座標を表す整数 aj と y座標を表す整数 bj が与えられる (-20,000 ≤ aj, bj ≤ 20,000, 1 ≤ j ≤ 4)．窓，カーテンともに，それぞれの頂点は反時計回り順に与えられる．また，窓，カーテンを表す図形はそれぞれ自己交差がない図形である．

入力の終わりは1つの 0 からなる行で示す．

Output

各データセットについて，カーテンに覆われていない窓の面積を 1 行に出力せよ．ただし，面積は必ず整数値になることに注意せよ．

Sample Input

4
0 0
10 0
10 10
0 10
0 0
5 0
5 10
0 10
6
0 0
10 0
10 5
5 5
5 10
0 10
2 0
8 0
8 10
2 10
12
1 1
1 3
-1 3
-1 1
-3 1
-3 -1
-1 -1
-1 -3
1 -3
1 -1
3 -1
3 1
2 2
-2 2
-2 -2
2 -2
4
20000 20000
-20000 20000
-20000 -20000
20000 -20000
1000 1000
-1000 1000
-1000 -1000
1000 -1000
4
1000 1000
-1000 1000
-1000 -1000
1000 -1000
20000 20000
-20000 20000
-20000 -20000
20000 -20000
4
0 0
10 0
10 10
0 10
20 0
30 0
30 10
20 10
0

Output for Sample Input

50
30
8
1596000000
0
100

Solution in Ruby (judge verdict: Accepted)

require 'set'

def compress(used_x)
	x_map = {}
	used_x.to_a.uniq.sort.each_with_index{|x, i| x_map[x] = i}
	x_map
end

loop do
    n = gets.to_i
    break if n == 0
    used_x = Set.new
    used_y = Set.new
    w_points = []
    n.times do
        x, y = gets.split.map(&:to_i)
        used_x << x
        used_y << y
        w_points << [x, y]
    end

    x_min = Float::INFINITY
    x_max = - x_min
    y_min = Float::INFINITY
    y_max = - y_min

    4.times do
        x, y = gets.split.map(&:to_i)
        used_x << x
        x_max = x if x > x_max
        x_min = x if x < x_min
        used_y << y
        y_max = y if y > y_max
        y_min = y if y < y_min
    end

    cx = compress(used_x)
    cy = compress(used_y)

    v_lines = []
    (w_points + [w_points[0]]).each_cons(2) do |p1, p2|
        x1, y1 = p1
        x2, y2 = p2
        next if x1 != x2
        y1, y2 = y2, y1 if y1 > y2
        v_lines << [cx[x1], cy[y1], cy[y2]]
    end
    v_lines.sort_by!(&:first)

    a = (0..cx.values.max).map { [0] * (cy.values.max + 1) }

    (0..cy.values.max).each do |y|
        crossed = v_lines.select {|x, y1, y2| y1 <= y && y < y2 }
        crossed.each_slice(2) do |l1, l2|
            x1, _, _ = l1
            x2, _, _ = l2
            (x1..x2-1).each do |x|
                a[x][y] = 1
            end
        end
    end

    (cy[y_min]..cy[y_max]-1).each do |y|
        (cx[x_min]..cx[x_max]-1).each do |x|
            a[x][y] = 0
        end
    end

    cx_inv = cx.invert
    cy_inv = cy.invert

    s = 0
    (0..cy.values.max).each do |y|
        (0..cx.values.max).each do |x|
            s += (cx_inv[x+1] - cx_inv[x]) * (cy_inv[y+1] - cy_inv[y]) if a[x][y] == 1
        end
    end

    p s
end