Atcoder 304 D - A Piece of Cake java题解

原题链接

题目描述

x y xy xy-平面上,一块带有一些草莓的蛋糕占据了一块矩形区域 { ( x , y ) : 0 ≤ x ≤ W , 0 ≤ y ≤ H } \{(x,y):0\le x\le W,0\le y\le H\} {(x,y):0xW,0yH}。蛋糕上有 N N N 个草莓,第 i i i 个草莓的坐标是 ( p i , q i ) (p_i,q_i) (pi,qi)。现在,高桥要用小刀按照以下规则将蛋糕切成小块。

  • 首先,沿着平行于 y y y 轴的 A A A 条直线:直线 x = a 1 x=a_1 x=a1、直线 x = a 2 x=a_2 x=a2、……、直线 x = a A x=a_A x=aA,将蛋糕切开。
  • 接着,沿着平行于 x x x 轴的 Y Y Y 条直线:直线 y = b 1 y=b_1 y=b1、直线 y = b 2 y=b_2 y=b2、……、直线 y = b B y=b_B y=bB,将蛋糕切开。

到了最后,蛋糕会被切成 ( A + 1 ) ( B + 1 ) (A+1)(B+1) (A+1)(B+1) 块长方形,现在高桥要选择其中一块,求他选择的蛋糕上草莓个数可能的最小值和最大值。保证切割的边缘线上没有草莓,具体请参照数据范围。

输入格式

输入共 ( 6 + N ) (6+N) (6+N) 行。
第一行两个整数 W , H W,H W,H
第二行一个整数 N N N
3 ∼ N + 2 3\sim N+2 3N+2 行,第 i + 2 i+2 i+2 行两个整数 p i , q i p_i,q_i pi,qi,即草莓的坐标。
N + 3 N+3 N+3 行,一个整数 A A A
接下来一行 A A A 个整数 a 1 a_1 a1 a 2 a_2 a2,……, a A a_A aA,即平行于 y y y轴的切割线。
N + 5 N+5 N+5 行,一个整数 B B B
接下来一行 B B B 个整数 b 1 b_1 b1 b 2 b_2 b2,……, b B b_B bB,即平行于 x x x轴的切割线。

输出格式

共一行用空格隔开的两个整数,第一个表示可能的最少的草莓数量,第二个表示可能的最多的草莓数量。

样例输入 #1
7 6
5
6 1
3 1
4 2
1 5
6 2
2
2 5
2
3 4
样例输出 #1
0 2
样例输入 #2
4 4
4
1 1
3 1
3 3
1 3
1
2
1
2
样例输出 #2
1 1
数据范围
  • 3 ≤ W , H ≤ 1 0 9 3 ≤ W, H ≤ 10^9 3W,H109
  • 1 ≤ N ≤ 2 × 1 0 5 1 ≤ N ≤ 2×10^5 1N2×105
  • 0 < p i < W , 0 < q i < H 0< p_i < W, 0< q_i <H 0<pi<W,0<qi<H
  • 1 ≤ A , B ≤ 2 × 1 0 5 1 ≤ A, B ≤ 2 ×10^5 1A,B2×105
public static void main(String[] args) throws IOException {
    int w = sc.nextInt(), h = sc.nextInt();
    int n = sc.nextInt();
    int[] p = new int[n], q = new int[n];
    for (int i = 0; i < n; i++) {
        p[i] = sc.nextInt(); q[i] = sc.nextInt();
    }
    int a = sc.nextInt();
    TreeSet<Integer> set1 = new TreeSet<Integer>();
    //添加0,这样左下角的草莓可以利用最近的左边的分割线和最近的下面的分割线来判断自己处于哪个区间
    set1.add(0);//添加0
    for (int i = 0; i < a; i++) {
        set1.add(sc.nextInt());
    }
    int b = sc.nextInt();
    TreeSet<Integer> set2 = new TreeSet<Integer>();
    set2.add(0);
    for (int i = 0; i < b; i++) {
        set2.add(sc.nextInt());
    }

	//HashMap的 key也可以使用字符串,坐标之前加个特殊符号拼接
    HashMap<ArrayList<Integer>, Integer> map = new HashMap<>();
    //遍历所有的草莓,为他们划分区间,所以在最后要判断是否有区间没有草莓(作为最小值0)
    for (int i = 0; i < n; i++) {
        //当两个 ArrayList 的元素内容和顺序相同,它们会生成相同的哈希码,被视为相等
        ArrayList<Integer> key = new ArrayList<>();
        key.add(set1.floor(p[i])); //找到最近的左边的分割线(题目保证了草莓不会在分割线上)
        key.add(set2.floor(q[i])); //找到最近的下面的分割线
        map.put(key, map.getOrDefault(key, 0) + 1);
    }

    int min = Integer.MAX_VALUE, max = 0;
    for (int val : map.values()) {
        min = Math.min(val, min);
        max = Math.max(val, max);
    }
    if (map.size() < (long) (a + 1) * (b + 1)) {//存在没有草莓的区间
        min = 0;
    }
    printWriter.println(min + " " + max);
}

考点

  • 当两个 ArrayList 的元素内容和顺序相同,它们会生成相同的哈希码,被视为相等
  • TreeSet 的 floor()方法的妙用
  • 一维模拟二维
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值