P4919 Marisa采蘑菇

知识点:扫描线,树状数组

原题面:Luogu

更好的阅读体验:My blog

最后扯一句,魔理沙世界第一可爱.jpg

简述

给定一长度为 \(n\) 的数列 \(a\),参数 \(k\)。给定 \(m\) 次询问。
每次询问给定区间 \([l,r]\),求区间内有多少个数,满足在区间内的出现次数与区间外的出现次数之差小于等于给定的常数 \(k\)。
\(1\le n,m\le 10^6\),\(0\le k\le 10^4\),\(0\le l\le r\le n\)。
3S,128MB。

分析

对于一个询问区间 \([l,r]\),设 \(s\) 为权值 \(x\) 在整个数列中出现的次数。考虑某种权值 \(x\) 对该区间有贡献的条件,显然为 \(|(s - x) - x|\le k\)。上式解得:

\[s - k\le 2\cdot x\le s k\]

考虑离线询问并排序,通过对询问进行扫描线固定询问的右端点。考虑在询问右端点单调右移的同时,对于每种权值,都维护它有所贡献的询问的左端点范围 \([L,R]\)。当询问的左端点 \(l\in [L,R]\) 时,区间 \([l,r]\) 内这种权值出现次数满足上式。右端点右移到下一个同权值位置时更新区间。如下图所示:

前缀 \([1,r]\) 中某权值出现次数满足上式时,有贡献的区间是数列的一段完整前缀,且需要注意 \(L,R\) 的初始取值,详见代码。

当扫描线枚举的右端点为 \(r\),维护上述信息后,询问 \([l,r]\) 的答案即为覆盖了左端点 \(l\) 的区间的个数。
发现上述算法需要支持区间修改,单点求和,树状数组维护即可,总复杂度 \(O(m\log m (n m)\log n)\) 级别。

代码

//知识点:扫描线,树状数组/*By:Luckyblock*/#include <algorithm>#include <cctype>#include <cstdio>#include <cstring>#define LL long longconst int kN = 1e6   10;//=============================================================struct Q {  int l, r, id;} q[kN];int n, m, k, col[kN], ans[kN];int last[kN], ne[kN], first[kN], sum[kN];//ne[i]:col[i] 之后第一个等于 col[i] 的位置//first[i]:颜色 i 在数列中第一次出现的位置//sum[i]:颜色 i 在数列中出现次数之和int cnt[kN], L[kN], R[kN];//在扫描线过程中维护,cnt[i]:到扫描位置为止 i 的出现次数//L[i]~R[i]:当前扫描位置作为询问右端点时,颜色 i 有贡献的询问左端点范围//=============================================================inline int read() {  int f = 1, w = 0;  char ch = getchar();  for (; !isdigit(ch); ch = getchar())    if (ch == '-') f = -1;  for (; isdigit(ch); ch = getchar()) w = (w << 3)   (w << 1)   (ch ^ '0');  return f * w;}void Chkmax(int &fir, int sec) {  if (sec > fir) fir = sec;}void Chkmin(int &fir, int sec) {  if (sec < fir) fir = sec;}bool CMP(Q fir_, Q sec_) {  if (fir_.r != sec_.r) return fir_.r < sec_.r;  return fir_.l < sec_.l;}namespace Bit {  #define low(x) (x&-x)  const int kLim = 1e6;  int t[kLim   10];  void Add(int pos_, int val_) {       pos_;    for (int i = pos_; i <= kLim; i  = low(i)) t[i]  = val_;  }  int Sum(int pos_) {       pos_;    int ret = 0;    for (int i = pos_; i; i -= low(i)) ret  = t[i];    return ret;  }  void Modify(int l_, int r_, int val_) {    Add(l_, val_);    Add(r_   1, -val_);  }}void Init() {  n = read(), m = read(), k = read();  for (int i = 1; i <= n;    i) {    col[i] = read();    if (   sum[col[i]] == 1) first[col[i]] = i;    last[col[i]] = n;  }  for (int i = n; i >= 1; -- i) {    ne[i] = last[col[i]];    last[col[i]] = i;  }  for (int i = 1; i <= m;    i) q[i] = (Q) {read(), read(), i};  std::sort(q   1, q   m   1, CMP);}void Modify(int pos_) {  int c = col[pos_], s = sum[c];     cnt[c];  if (R[c]) Bit::Modify(L[c], R[c], -1); //减去之前颜色 i 对询问左端点的贡献  if (2 * cnt[c] >= s - k) R[c] = R[c] ? ne[R[c]] : first[c]; //右端点左移,增加区间内该权值出现次数。  if (2 * cnt[c] > s   k) L[c] = L[c] ?  ne[L[c] - 1]   1 : first[c]   1; //左端点右移,减小区间内该权值出现次数。注意开区间。  if (R[c]) Bit::Modify(L[c], R[c], 1);}//=============================================================int main() {   Init();  for (int i = 1, nowr = 0; i <= m;    i) {    while (nowr < q[i].r && nowr < n) Modify(   nowr); //扫描位置更新    ans[q[i].id] = Bit::Sum(q[i].l);  }  for (int i = 1; i <= m;    i) printf("%d\n", ans[i]);  return 0; }

来源:https://www.icode9.com/content-4-864651.html

(0)

相关推荐

  • 【学员专栏012期】题解 P5523 【[yLOI2019] 珍珠】-黄子睿

    作者:黄子睿 ID:huangzirui 学校:长沙市中雅培粹新九年级 获奖:2019年提高组一等奖,普及组一等奖(满分) 博客地址:https://www.luogu.com.cn/blog/My- ...

  • 分型

    分型有顶分形,底分型两种.这里主要讲解的不是标准的底分型顶分型,而是解决大家在非标准分型形态上的划分.首先组成顶分型的三根K线和组成底分型的三根K线必须没有任何重叠的区间.其次分型形态中间的哪根K线必 ...

  • 这几天,你采蘑菇了吗?

    ↑精彩视频,汝城亲,赶紧一睹为快!↑ 小时候听过一首耳熟能详 名曰<采蘑菇的小姑娘>的歌儿 这几天气温回暖 恰逢南风天来袭 纯天然的野生蘑菇 就在此时 闪亮登场了 蘑菇出现在山林中 不仅疯 ...

  • 第一次参加驴友活动徒步山林采蘑菇

    前几天,好友惠和我说要去采蘑菇.不得不说,对于我们做护士来说,星期六休息都是奢侈的,于是我和科室里李姐串了一个班.在这里要感谢李姐哦,惠说是群里的一个驴友发起来的.说好了是7点30.一直以来我都是一个 ...

  • 采蘑菇的三兰子

    天还没有完全亮,山村还笼罩晨雾之中,只是隐约看得见房屋的轮廓,响彻村庄的只有那此起彼伏的鸡叫声.连野鸟都还没有开始啼叫,三兰子就爬起床,胡乱地上个厕所,洗一把脸,背上大背篓,出了门. 这些天的天气不冷 ...

  • 动画片--采蘑菇

    动画片--采蘑菇

  • 【江西】郑欣悦《采蘑菇》指导老师:林晓春

    采蘑菇 定南县第三小学五年级 郑欣悦 "啦啦啦,啦啦啦--"我一边提着小篮子,一边哼着小曲,在这因为刚下过一场雨,而变得湿漉漉的小森林里快活地采着蘑菇. 平时采蘑菇,都是有家人伴在 ...

  • 【陈志军*精品】春天里采蘑菇的女孩.

    诗梦撷英文学第1306期 [春天里采蘑菇的女孩] 作者:陈志军.主播:星辰.主编:玫瑰 收听以上音频朗诵 阳光明媚的清晨 她在芳草地里 寻找着蘑菇 蹲下腰 两个眼睛眨一眨 脸上充满着欢笑的气息 满满的 ...

  • 【寻找“小歌星”】翁 琳 ║小伙伴采蘑菇

    月20 寻找"小歌星" (第6期) 今天分享原创儿歌 <小伙伴采蘑菇> 唱:翁 琳 词:毕健民 曲:楼 勤 编:张仲健 小伙伴采蘑菇 作词:毕健民 柔柔的阳光雨后照, ...

  • 走!去瑞典采蘑菇!附: 瑞典菌类图鉴

    @这里是瑞典  FollowLOCALSWEDEN 你 就是我的 小蘑菇 来瑞典之前,对于蘑菇的认知还停留在平菇.香菇.金针菇这几种,后来参加了一次野外蘑菇采摘,才发现有那么多的蘑菇品种,都是饕餮美食 ...

  • 谭喜爱:采蘑菇

    采蘑菇 谭喜爱 阴雨靡靡的江南三月,大地一片生机盎然:山村房前屋后,一树树桃花如烈火:田野里油菜金灿灿似满地黄金:池塘里水田里,青蛙把一面面大鼓敲得铿锵:山野上树木葱茏,地上厚厚的松针宛如一床大山的被 ...