AOJ0509 Sheets
問題リンク Sheets
- 解法
a[y][x]: 左下の座標が(x, y)である1*1のマスを覆うシートの数
という表をyについて1行ずつ更新する方法で解くことができました。
シートの枚数が変わるタイミングはシートの上辺と下辺の部分です。
面積はa[y][x]が正になっている部分の総和で、辺の長さは、正であるa[y][x]の近傍4マスを見て0となっているマスの数の和になります。
10^8近い計算量に膨らむことになりますが、何とか間に合ってくれるようです。
- ソース
import java.util.ArrayList; import java.util.Arrays; import java.util.List; //Sheets public class AOJ0509 { class Scanner { int nextInt() { try { int c = System.in.read(); while (c != '-' && (c < '0' || '9' < c)) c = System.in.read(); if (c == '-') return -nextInt(); int res = 0; do { res *= 10; res += c - '0'; c = System.in.read(); } while ('0' <= c && c <= '9'); return res; } catch (Exception e) { return -1; } } } class R{ int x1, x2, type; public R(int x1, int x2, int type) { this.x1 = x1; this.x2 = x2; this.type = type; } } int n, r, area, len, INF = 1<<28; int[][] a; List<R>[] list; @SuppressWarnings("unchecked") void run(){ Scanner sc = new Scanner(); a = new int[2][10000]; list = new List[10001]; for(;;){ n = sc.nextInt(); r = sc.nextInt(); if((n|r)==0)break; int minx = INF, maxx = -1, miny = INF, maxy = -1; area = len = 0; for(int i=0;i<=10000;i++)list[i] = new ArrayList<R>(); for(int i=0;i<n;i++){ int x1 = sc.nextInt(), y1 = sc.nextInt(), x2 = sc.nextInt(), y2 = sc.nextInt(); minx = Math.min(minx, x1); maxx = Math.max(maxx, x2); miny = Math.min(miny, y1); maxy = Math.max(maxy, y2); list[y1].add(new R(x1, x2, 1)); list[y2].add(new R(x1, x2, -1)); } Arrays.fill(a[0], 0); int X = 1; for(int y=miny;y<=maxy+1;y++,X=1-X){ for(int x=minx;x<maxx;x++)a[X][x]=a[1-X][x]; for(R r:list[y]){ for(int x=r.x1;x<r.x2;x++)a[X][x]+=r.type; } for(int x=minx;x<maxx;x++){ if(0 < a[X][x]){ area++; if(x==0 || a[X][x-1]==0)len++; if(x==9999 || a[X][x+1]==0)len++; } if(a[X][x]==0&&0<a[1-X][x] || 0<a[X][x]&&a[1-X][x]==0)len++; } } System.out.println(area); if(r==2)System.out.println(len); } } public static void main(String[] args) { new AOJ0509().run(); } }