贡献法:孤独的照片
孤独的照片
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);
}
}
1036

被折叠的 条评论
为什么被折叠?



