CF1278C-Berry Jam-(前缀和)

https://vjudge.net/problem/CodeForces-1278C

题意:有2n瓶果酱,中间有一个楼梯隔开,从中间往左或右两边清空果酱,使得两种果酱的数量相等,最少要清空多少瓶

题解:

拿掉果酱只能从中间往左边或者往右边拿,并且只能连续拿,很容易想到前缀和。
可以将果酱分割成两部分,左右前缀和。
用-1替换果酱2,计算前后缀和的时候以0为标准,表示果酱的数量。
正数表示果酱1的数量>果酱2的数量,负数表示果酱2的数量>果酱1的数量,0表示果酱1=果酱2的数量
举例说明
原数据
1 2 1 2 2 2 1 2
修改2变成-1
1 -1 1 -1 -1 -1 1 -1
左右两边用前后缀和计算
1 0 1 0 -2 -1 0 -1
对于前缀和为x的情况,只需要找到后缀和为-x的位置,将二者之间的果酱取下,就能保证剩余的果酱类型,数量相同。
对于相同的x,前缀和的idx越大越好,表示从中间往左边取物品数量越少。后缀和的idx越小越好,表示从中间往右边取物品数量越少。这里有贪心思想。

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * @Date 2022/4/6
 */
public class Main {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int t = scan.nextInt();
        while (t-- > 0) {
            int n = scan.nextInt();
            int[] prefix = new int[n + 1];
            Map<Integer, Integer> prefixNumIdxMap = new HashMap<>();
            //左半部分
            for (int i = 1; i <= n; i++) {
                int x = scan.nextInt();
                if (x == 1) {
                    prefix[i] = prefix[i - 1] + 1;
                }
                else {
                    prefix[i] = prefix[i - 1] - 1;
                }
                //前缀的值,对应的索引i越来越大,越大越好,表示从中间往左边取物品数量越少
                prefixNumIdxMap.put(prefix[i], i);
            }
            //右半部分输入,将2替换成-1,用于计算后缀和
            int[] suffix = new int[n + 2];
            Map<Integer, Integer> suffixNumIdxMap = new HashMap<>();
            for (int i = 1; i <= n; i++) {
                int x = scan.nextInt();
                if (x != 1) {
                    x = -1;
                }
                suffix[i] = x;
            }
            for (int i = n; i >= 1; i--) {
                suffix[i] += suffix[i + 1];
                //后缀的值,对应的索引i越来越小,越小越好,表示从中间往右边取物品数量越少
                suffixNumIdxMap.put(suffix[i], i);
            }

            int ans = 2 * n;
            //前后缀和封顶是-n和n
            for (int i = -n; i <= n; i++) {
                if (prefixNumIdxMap.containsKey(i) && prefixNumIdxMap.get(i) != 0 && suffixNumIdxMap.containsKey(-i) && suffixNumIdxMap.get(-i) != 0 || i == 0) {
                    ans = Math.min(ans, n - prefixNumIdxMap.getOrDefault(i, 0) + suffixNumIdxMap.getOrDefault(-i, n + 1) - 1);
                }
            }
            System.out.println(ans);
        }
    }

}

 

 

posted @ 2019-12-21 01:31  守林鸟  阅读(377)  评论(0编辑  收藏  举报