【P6307】选择客栈 加强版

【P6307】选择客栈 加强版

Description

给定一个两个序列 AB,求满足 i<jAi=Ajmink=ijp 的点对 (i,j) 个数。

Limitations

序列长度不超过 106

Solution

又是点对题,套路做法是枚举右端点,然后想办法干掉左端点。

考虑对于一个右端点 r,合法的左端点个数即为 r 左侧第一个费用不大于 p 的位置 x 的左侧的同颜色个数。可以考虑对每种颜色做一个前缀和维护前缀该颜色个数,然后查询 r 的颜色在 x 位置的前缀和值即可。时间复杂度 O(nk),可以通过 80 分的数据。当然可以使用可持久化线段树维护这些前缀和,但是这里考虑一种复杂度更低的做法。

注意到 p 是给定的,因此当右端点 r 增大时,位置 x 不会变小,而任何时刻大于 x 的位置的颜色个数是不需要统计的,因为不会产生贡献。因此我们只维护当前的 x 及其左侧的位置的每种颜色的个数即可。当碰到某个位置的费用不高于 p 时,则将该位置左侧所有没有被计算个数的位置都加入贡献,然后更新 x 即可。考虑时间复杂度,每个位置只会被计算一次贡献,因此总时间复杂度 O(n)

所以毒瘤鱼鱼为什么不把 k 出到与 n 同阶呢

Code

#include <cstdio>

const int maxn = 2000005;

int n, k, p;
ll ans;
int col[maxn], fee[maxn], cnt[maxn];

int main() {
  freopen("1.in", "r", stdin);
  qr(n); qr(k); qr(p);
  for (int i = 1; i <= n; ++i) {
    qr(col[i]); qr(fee[i]);
    if (fee[i] <= p) {
      for (int j = i - 1; fee[j] > p; --j) {
        ++cnt[col[j]];
      }
    }
    ans += cnt[col[i]];
    if (fee[i] <= p) {
      ++cnt[col[i]];
    }
  }
  printf("%lld\n", ans);
}

posted @   一扶苏一  阅读(252)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示