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