贡献法:孤独的照片

贡献法:孤独的照片

孤独的照片

www.acwing.com/problem/content/4264/

在这里插入图片描述

贡献法通俗了解就是换个视角看问题,看谁对答案的贡献更大,选择哪个维度进行解答

  • O ( n l o g n ) O(nlogn) O(nlogn)

  • 孤独的区间中会出现单独的一个字母

  • 一个孤独的区间必然会对应唯一孤独的牛

  • 统计有多少个孤独区间 -> 统计每一头牛在多少个孤独区间

    • O ( n 2 ) − > O ( n ) O(n^2) -> O(n) O(n2)>O(n)
  • 找出孤独的牛(以 G 为例)

    • 左右两边各有一个 H

      • 区间个数为 L ( H ) ∗ R ( H ) L(H) * R(H) L(H)R(H)
    • 左边无 H,右边至少有 2 个 H

      • 区间个数为 R ( H ) − 1 R(H)-1 R(H)1
    • 右边无 H,左边至少有 2 个 H

      • 区间个数为 L ( H ) − 1 L(H)-1 L(H)1
    • 即找到孤独牛后可以使用 O ( 1 ) O(1) O(1) 代价算出区间个数

    • 使用数组预处理连续的字符数量

import java.util.Scanner;

public class Main {
    static final int N = 500010;
    static char[] cow;
    static int[] ls = new int[N], rs = new int[N];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        cow = sc.next().toCharArray();

        // 初始化连续的H和G的长度数组
        // ls[i]表示在i左侧有多少连续个与i不同的牛;rs[i]表示在i右侧有多少连续个与i不同的牛
        char preCow = cow[0];
        ls[0] = 0;
        int count = 1;
        for (int i = 1; i < n; i++) {
            if (cow[i] == preCow) {
                ls[i] = 0;
                count++;
            } else {
                ls[i] = count;
                count = 1;
                preCow = cow[i];
            }
        }

        preCow = cow[n - 1];
        rs[n - 1] = 0;
        count = 1;
        for (int i = n - 2; i >= 0; i--) {
            if (cow[i] == preCow) {
                rs[i] = 0;
                count++;
            } else {
                rs[i] = count;
                count = 1;
                preCow = cow[i];
            }
        }

        // 判断每头牛是否为孤独牛
        // 将判断区间的操作转换为判断牛的操作
        long res = 0;
        for (int i = 0; i < n; i++) {
            // 全取左,全取右,左右都有取
            if (ls[i] >= 2) {
                res += ls[i] - 1;
            }
            if (rs[i] >= 2) {
                res += rs[i] - 1;
            }
            if (ls[i] + rs[i] >= 2) {
                res += (long) ls[i] * rs[i];
            }
        }
        System.out.println(res);
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值