fork(1) download
  1. /* paiza POH! vol.2
  2.  * result:
  3.  * http://p...content-available-to-author-only...a.jp/poh/paizen/result/16ee5b809fc9a60cf232532f432464af
  4.  * author: Leonardone @ NEETSDKASU
  5.  */
  6. import java.util.*;
  7. import java.lang.*;
  8. import java.lang.ref.*;
  9. import java.io.*;
  10.  
  11.  
  12. class Main
  13. {
  14. public static void main (String[] args) throws java.lang.Exception
  15. {
  16.  
  17. String[] hw = in.readLine().split(" ");
  18. int H = Integer.parseInt(hw[0]); // ホーム画面縦の区画数
  19. int W = Integer.parseInt(hw[1]); // ホーム画面横の区画数
  20.  
  21. int[][] home = new int[H][W];
  22.  
  23. for (int y = 0; y < H; y++)
  24. {
  25. String line = in.readLine();
  26. for (int x = 0; x < W; x++)
  27. {
  28. home[y][x] = (int)(line.charAt(x) - '0');
  29. }
  30. }
  31.  
  32. int N = Integer.parseInt(in.readLine()); // ウィジェット数
  33.  
  34. WidgetTree tree = new WidgetTree();
  35. Set<Widget> set = new HashSet<Widget>(N);
  36. Widget[] list = new Widget[N];
  37.  
  38. for (int i = 0; i < N; i++)
  39. {
  40. String[] st = in.readLine().split(" ");
  41. int s = Integer.parseInt(st[0]); // ウィジェットの縦サイズ
  42. int t = Integer.parseInt(st[1]); // ウィジェットの横サイズ
  43.  
  44. list[i] = Widget.getWidget(s, t);
  45.  
  46. if (s <= H && t <= W)
  47. {
  48. if (set.add(list[i]))
  49. {
  50. tree.add(list[i]);
  51. }
  52. }
  53.  
  54. }
  55.  
  56. tree.calc(H, W, home);
  57.  
  58. for (Widget widget : list)
  59. {
  60. System.out.println(widget.getAnswer());
  61. }
  62.  
  63. } // end of main(String[])
  64. }
  65.  
  66.  
  67. class Widget
  68. {
  69. private static Widget[] pool = new Widget[90604];
  70.  
  71. public static Widget getWidget(int s, int t)
  72. {
  73. int index = s * 301 + t;
  74. if (pool[index] == null)
  75. {
  76. pool[index] = new Widget(s, t);
  77. }
  78. return pool[index];
  79. }
  80.  
  81. private final int s;
  82. private final int t;
  83. private int answer = 0;
  84. private Widget(int s, int t)
  85. {
  86. this.s = s;
  87. this.t = t;
  88. }
  89.  
  90. public int getS()
  91. {
  92. return s;
  93. }
  94.  
  95. public int getT()
  96. {
  97. return t;
  98. }
  99.  
  100. public int getAnswer()
  101. {
  102. return answer;
  103. }
  104.  
  105. public int setAnswer(int answer)
  106. {
  107. this.answer = answer;
  108. return answer;
  109. }
  110.  
  111. @Override
  112. public int hashCode()
  113. {
  114. return s * 301 + t;
  115. }
  116.  
  117. @Override
  118. public boolean equals(Object obj)
  119. {
  120. if (this == obj) return true;
  121. if (obj == null) return false;
  122. if (this.getClass().equals(obj.getClass()) == false) return false;
  123. Widget widget = (Widget)obj;
  124. return this.s == widget.s && this.t == widget.t;
  125. }
  126.  
  127. @Override
  128. public String toString()
  129. {
  130. return "[" + s + "," + t + "]";
  131. }
  132.  
  133. public enum Extend
  134. {
  135. S_PARENT, S_CHILD, T_PARENT, T_CHILD,
  136. SAME, IMPOSSIBLE, PRE_T_CHILD, PRE_S_CHILD,
  137. PRE_PARENT
  138. }
  139.  
  140. public Extend getExtend(Widget widget)
  141. {
  142. if (this.s == widget.s && this.t == widget.t)
  143. {
  144. return Extend.SAME;
  145. }
  146. if (this.s == widget.s)
  147. {
  148. if (this.t < widget.t)
  149. {
  150. return Extend.T_CHILD;
  151. }
  152. return Extend.T_PARENT;
  153. }
  154. if (this.t == widget.t)
  155. {
  156. if (this.s < widget.s)
  157. {
  158. return Extend.S_CHILD;
  159. }
  160. return Extend.S_PARENT;
  161. }
  162. if (this.s < widget.s && this.t < widget.t)
  163. {
  164. if (widget.s < widget.t)
  165. {
  166. return Extend.PRE_T_CHILD;
  167. }
  168. return Extend.PRE_S_CHILD;
  169. }
  170. if (this.s > widget.s && this.t > widget.t)
  171. {
  172. return Extend.PRE_PARENT;
  173. }
  174. return Extend.IMPOSSIBLE;
  175. }
  176. }
  177.  
  178. class WidgetTree
  179. {
  180. private class Node
  181. {
  182. final Widget widget;
  183. WeakReference<Node> t_parent = null;
  184. WeakReference<Node> s_parent = null;
  185. Node t_child = null;
  186. Node s_child = null;
  187. Queue<Node> pre_s_child = new ArrayDeque<Node>();
  188. Queue<Node> pre_t_child = new ArrayDeque<Node>();
  189. Node(Widget widget)
  190. {
  191. this.widget = widget;
  192. }
  193.  
  194. public int childrenCount()
  195. {
  196. return (t_child != null ? 1 : 0)
  197. + (s_child != null ? 1: 0)
  198. + pre_s_child.size()
  199. + pre_t_child.size();
  200. }
  201.  
  202. @Override
  203. public String toString()
  204. {
  205. return "<" + widget + ";" + t_child
  206. + ";" + s_child + ";("
  207. + pre_t_child + ");(" + pre_s_child + ")>";
  208. }
  209. }
  210.  
  211. private Node root = new Node(Widget.getWidget(1,1));
  212.  
  213. @Override
  214. public String toString()
  215. {
  216. return root.toString();
  217. }
  218.  
  219. private enum Family { T_FAMILY, S_FAMILY }
  220.  
  221. private boolean setFamily(Node parent, Node child, Family family)
  222. {
  223. if (parent == null || child == null || family == null)
  224. {
  225. return false;
  226. }
  227. switch (family)
  228. {
  229. case T_FAMILY:
  230. parent.t_child = child;
  231. child.t_parent = new WeakReference<Node>(parent);
  232. break;
  233. case S_FAMILY:
  234. parent.s_child = child;
  235. child.s_parent = new WeakReference<Node>(parent);
  236. break;
  237. default:
  238. return false;
  239. }
  240. return true;
  241. }
  242.  
  243. private Node joint(Node node1, Node node2)
  244. {
  245.  
  246. Node temp = null, temp2 = null, temp3 = null;
  247. int n;
  248.  
  249. Widget.Extend e = node1.widget.getExtend(node2.widget);
  250. switch (e)
  251. {
  252. case T_PARENT:
  253. {
  254. if (node2.t_child != null)
  255. {
  256. temp = joint(node2.t_child, node1);
  257. setFamily(node2, temp, Family.T_FAMILY);
  258. }
  259. else
  260. {
  261. setFamily(node2, node1, Family.T_FAMILY);
  262. }
  263. n = node2.pre_t_child.size();
  264. for (int i = 0; i < n; i++)
  265. {
  266. temp2 = node2.pre_t_child.poll();
  267. temp3 = joint(node2.t_child, temp2);
  268. if (temp3 == null)
  269. {
  270. node2.pre_t_child.offer(temp2);
  271. }
  272. else
  273. {
  274. setFamily(node2, temp3, Family.T_FAMILY);
  275. }
  276. }
  277. return node2;
  278. }
  279. case S_PARENT:
  280. {
  281. if (node2.s_child != null)
  282. {
  283. temp = joint(node2.s_child, node1);
  284. setFamily(node2, temp, Family.S_FAMILY);
  285. }
  286. else
  287. {
  288. setFamily(node2, node1, Family.S_FAMILY);
  289. }
  290. n = node2.pre_s_child.size();
  291. for (int i = 0; i < n; i++)
  292. {
  293. temp2 = node2.pre_s_child.poll();
  294. temp3 = joint(node2.s_child, temp2);
  295. if (temp3 == null)
  296. {
  297. node2.pre_s_child.offer(temp2);
  298. }
  299. else
  300. {
  301. setFamily(node2, temp3, Family.S_FAMILY);
  302. }
  303. }
  304. return node2;
  305. }
  306. case T_CHILD:
  307. case S_CHILD:
  308. {
  309. return joint(node2, node1);
  310. }
  311. case PRE_S_CHILD:
  312. {
  313. if (node1.s_child != null)
  314. {
  315. temp = joint(node1.s_child, node2);
  316. setFamily(node1, temp, Family.S_FAMILY);
  317. }
  318. if (temp == null)
  319. {
  320. if (node1.pre_s_child.isEmpty())
  321. {
  322. node1.pre_s_child.offer(node2);
  323. }
  324. else
  325. {
  326. n = node1.pre_s_child.size();
  327. for (int i = 0; i < n; i++)
  328. {
  329. temp2 = node1.pre_s_child.poll();
  330. temp3 = joint(temp2, node2);
  331. if (temp3 != null)
  332. {
  333. node1.pre_s_child.offer(temp3);
  334. break;
  335. }
  336. node1.pre_s_child.offer(temp2);
  337. }
  338. if (temp3 == null)
  339. {
  340. node1.pre_s_child.offer(node2);
  341. }
  342. }
  343. }
  344. return node1;
  345. }
  346. case PRE_T_CHILD:
  347. {
  348. if (node1.t_child != null)
  349. {
  350. temp = joint(node1.t_child, node2);
  351. setFamily(node1, temp, Family.T_FAMILY);
  352. }
  353. if (temp == null)
  354. {
  355. if (node1.pre_t_child.isEmpty())
  356. {
  357. node1.pre_t_child.offer(node2);
  358. }
  359. else
  360. {
  361. n = node1.pre_t_child.size();
  362. for (int i = 0; i < n; i++)
  363. {
  364. temp2 = node1.pre_t_child.poll();
  365. temp3 = joint(temp2, node2);
  366. if (temp3 != null)
  367. {
  368. node1.pre_t_child.offer(temp3);
  369. break;
  370. }
  371. else
  372. {
  373. node1.pre_t_child.offer(temp2);
  374. }
  375. }
  376. if (temp3 == null)
  377. {
  378. node1.pre_t_child.offer(node2);
  379. }
  380. }
  381. }
  382. return node1;
  383. }
  384. case SAME:
  385. {
  386. return node1;
  387. }
  388. case PRE_PARENT:
  389. case IMPOSSIBLE:
  390. default:
  391. {
  392. break;
  393. }
  394. }
  395. return null;
  396. }
  397.  
  398.  
  399. public boolean add(Widget widget)
  400. {
  401. Node temp = joint(root, new Node(widget));
  402. if (temp == null)
  403. {
  404. return false;
  405. }
  406. root = temp;
  407. return true;
  408. }
  409.  
  410. private void calc(Node parent, Node child, int[][]array, int h, int w, boolean nocopy)
  411. {
  412. calc(child, parent.widget.getS(), parent.widget.getT(), array, h, w, nocopy);
  413. }
  414.  
  415.  
  416. private void calc(Node node, int s, int t, int[][] array, int h, int w, boolean nocopy)
  417. {
  418. if (node == null)
  419. {
  420. return;
  421. }
  422. int ds = node.widget.getS() - s;
  423. int dt = node.widget.getT() - t;
  424. int hh = h - ds;
  425. int ww = w - dt;
  426. int[][] temp;
  427. if (nocopy)
  428. {
  429. temp = array;
  430. }
  431. else
  432. {
  433. temp = new int[hh][ww];
  434. }
  435. int count = 0;
  436. for (int i = 0; i < hh; i++)
  437. {
  438. for (int j = 0; j < ww; j++)
  439. {
  440. for (int dy = 0; dy <= ds; dy++)
  441. {
  442. for (int dx = 0; dx <= dt; dx++)
  443. {
  444. temp[i][j] += array[i + dy][j + dx];
  445. }
  446. }
  447. if (temp[i][j] == 0)
  448. {
  449. count++;
  450. }
  451. }
  452. }
  453. node.widget.setAnswer(count);
  454. nocopy = node.childrenCount() < 2;
  455. calc(node, node.t_child, temp, hh, ww, nocopy);
  456. calc(node, node.s_child, temp, hh, ww, nocopy);
  457. for (Node p : node.pre_t_child)
  458. {
  459. calc(node, p, temp, hh, ww, nocopy);
  460. }
  461. for (Node p : node.pre_s_child)
  462. {
  463. calc(node, p, temp, hh, ww, nocopy);
  464. }
  465. }
  466.  
  467. public void calc(int h, int w, int[][] home)
  468. {
  469. calc(root, 1, 1, home, h, w, false);
  470. }
  471. }
  472.  
  473.  
Success #stdin #stdout 0.08s 380288KB
stdin
8 30
000000100010011000000100010011
001001100001010000010001010101
000010001010101000010001001010
100000001001100000000100010011
100000001010011000010001010101
000010001001010000010001001010
110000111010101000000100010011
000010001010100000010001010100
24
2 2
2 3
3 2
2 2
2 3
3 4
4 4
3 3
2 3
4 3
300 12
53 299
1 2
4 7
3 10
10 3
2 5
4 4
8 4
2 1
8 8
8 5
1 1
6 7
7 1
4 2
2 7
4 1
1 8
3 3
4 4
5 5
2 2
3 2
3 4
stdout
46
26
29
46
26
6
5
16
26
12
0
0
104
0
0
0
3
5
1
103
0
0
167
0