题目
题目链接
解题思路
这道题的关键点在于:
- \(n\) 个点形成一条链,边的编号从 \(1\) 到 \(n-1\)
- 对于第 \(i\) 条边,其权值 \(w_i\) 定义为:在第 \(i\) 条边左侧 \((x \leq i)\) 且点权为 \(y\) 的点数,与在第 \(i\) 条边右侧 \((y > i)\) 且点权为 \(y\) 的点数的乘积之和
- 需要计算每条边的权值
解题思路:
- 使用两个哈希表分别记录左侧和右侧的点权计数
- 初始时所有点都在右侧
- 从左到右遍历每个位置,计算当前边的权值:
- 对于每个不同的点权值,贡献为左侧该值的个数 × 右侧该值的个数
- 移动当前点到左侧,更新计数
代码
#include <iostream>
#include <unordered_map>
using namespace std;int nums[100005];void solve(int n) {long long pre = 0;unordered_map<int, int> left, right;// 初始时所有点都在右侧for (int i = n - 1; i >= 0; --i)right[nums[i]]++;// 计算每条边的权值for (int i = 0; i < n - 1; ++i) {// 计算当前边的权值并输出printf("%lld%c", pre += n - 2 * i - right[nums[i]] + left[nums[i]], i == n - 2 ? '\n' : ' ');// 将当前点从右侧移到左侧right[nums[i]]--;left[nums[i]]++;}
}int main() {int n;scanf("%d", &n);for (int i = 0; i < n; ++i)scanf("%d", &nums[i]);solve(n);return 0;
}
import java.util.*;public class Main {public static void solve(int n, int[] nums) {long pre = 0;Map<Integer, Integer> left = new HashMap<>();Map<Integer, Integer> right = new HashMap<>();// 初始时所有点都在右侧for (int i = n - 1; i >= 0; i--) {right.put(nums[i], right.getOrDefault(nums[i], 0) + 1);}// 计算每条边的权值for (int i = 0; i < n - 1; i++) {pre += n - 2 * i - right.getOrDefault(nums[i], 0) + left.getOrDefault(nums[i], 0);System.out.print(pre + (i == n - 2 ? "\n" : " "));// 将当前点从右侧移到左侧right.put(nums[i], right.get(nums[i]) - 1);left.put(nums[i], left.getOrDefault(nums[i], 0) + 1);}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[] nums = new int[n];for (int i = 0; i < n; i++) {nums[i] = sc.nextInt();}solve(n, nums);}
}
def solve(n, nums):pre = 0left = {}right = {}# 初始时所有点都在右侧for x in nums:right[x] = right.get(x, 0) + 1# 计算每条边的权值for i in range(n-1):pre += n - 2 * i - right.get(nums[i], 0) + left.get(nums[i], 0)print(pre, end='\n' if i == n-2 else ' ')# 将当前点从右侧移到左侧right[nums[i]] -= 1left[nums[i]] = left.get(nums[i], 0) + 1n = int(input())
nums = list(map(int, input().split()))
solve(n, nums)
算法及复杂度
- 算法:哈希表 + 动态维护
- 时间复杂度:\(\mathcal{O}(n)\) - 只需要遍历一次数组
- 空间复杂度:\(\mathcal{O}(n)\) - 需要两个哈希表存储点权计数