T815912

我们先要吧公式搞好。

for (int i = 1; i <= n; i++) {
    // 若 a[i] 之前出现过,撤销旧的贡献
    if (last[a[i]]) 
        update(1, 1, n, llast[a[i]] + 1, last[a[i]], 1);
        // 注意:这里参数是 1,配合下面的"查询"逻辑理解
        // 通常这里的实现是:在 [llast+1, last] 区间 -1,
        // 但代码用了 +1 并配合前缀/后缀查询方式,
        // 具体取决于 update/query 的定义
    
    // 更新出现位置
    llast[a[i]] = last[a[i]];
    last[a[i]] = i;
    
    // 处理所有右端点为 i 的查询
    for (int x : qrt[i])
        ans[x] = query(1, 1, n, ql[x]);
}
  • 当遍历到位置 \(i\),值为 \(v = a_i\):

    若 \(v\) 之前出现过(last[v] != 0),说明原来在 \(last_v\) 处的"贡献 \(1\)"要撤销,改到 \(i\) 处贡献。

    撤销方式:在区间 \(llast_v + 1 \sim last_v\) 上加 \(-1\)(因为只有左端点落在这个区间内的查询,才会包含 \(last_v\) 这个位置而不包含 \(i\))。

    然后在位置 \(i\) 加 \(1\)。

posted @ 2026-09-12 16:46  yingMC  阅读(5)  评论(0)    收藏  举报