P4168 [Violet]蒲公英

题意

题目背景

亲爱的哥哥:

你在那个城市里面过得好吗?

我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……

最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!

哥哥你要快点回来哦!

爱你的妹妹 \(Violet\)

\(Azure\) 读完这封信之后微笑了一下。

“蒲公英吗……”

题目描述

在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。

为了简化起见,我们把所有的蒲公英看成一个长度为\(n\)的序列\((a_1,a_2\cdots a_n)\),其中\(a_i\)为一个正整数,表示第\(i\)棵蒲公英的种类编号。

而每次询问一个区间\([l,r]\),你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。

注意,你的算法必须是在线的

输入输出格式

输入格式:

第一行两个整数\(n,m\),表示有\(n\)株蒲公英,\(m\)次询问。

接下来一行\(n\)个空格分隔的整数\(a_i\),表示蒲公英的种类

再接下来\(m\)行每行两个整数\(l_0,r_0\),我们令上次询问的结果为\(x\)(如果这是第一次询问,则\(x=0\))。

令\(l=(l_0+x-1)\bmod n + 1,r=(r_0+x-1)\bmod n + 1\),如果\(l>r\),则交换\(l,r\)。

最终的询问区间为[l,r]。

输出格式:

输出\(m\)行。每行一个整数,表示每次询问的结果。

输入输出样例

输入样例#1:

6 3
1 2 3 2 1 2
1 5
3 6
1 5

输出样例#1:

1
2
1

说明

对于\(20\%\)的数据,保证\(1\le n,m\le 3000\)。

对于\(100\%\)的数据,保证\(1\le n\le 40000,1\le m\le 50000,1\le a_i\le 10^9\)。

思路

\(600\ AC\)!整理博客。 --Uranus

重新拾起分块这个毒瘤东西,并在\(alecli\)大佬的推荐下做了这道题。

我们把序列分成块,离散化之后记录每个数字在各个块内出现的次数,那么出现最多的就是众数了。这里我用数组\(s[i][j][k]\)表示第\(i\)块到第\(j\)块数字\(k\)的出现次数。然后我们统计区间众数,用\(md[i][j]\)记录众数大小,\(tms[i][j]\)记录众数出现次数。

预处理到这里就结束了,接下来考虑查询操作。对于每次查询的区间,一定是由一个大块和这个大块左边的一些数,以及右边的一些数组成的,那么显然,这个区间最后的众数为大块的众数,或者大块左边出现的数,或者大块右边出现的数。

那么我们就直接用之前统计出的大块的三个数组,在这个基础上把左右两小块用预处理时的相同方法加进来,统计答案后再把小块去掉,就可以很方便的查询并保持预处理数组了。

既然是分块,那么细节一定是很多的,具体来说有这几条:

  • 注意离散化,注意常数优化。
  • 如果查询区间不包含大块,直接把两个小块暴力处理。
  • \(alecli\)说分块的大小会影响时间复杂度,并告诉我块的大小最好为\(n^\frac{2}{3}\),虽然并不知道为什么。

只要耐心调试,最终一定能\(AC\)的,祝你好运!

AC代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=4e4+5,MAXM=45;
int n,m,len,ans,cnt,a[MAXN],b[MAXN],c[MAXN];
int sz,num,l[MAXM],r[MAXM],belong[MAXN],s[MAXM][MAXM][MAXN],md[MAXM][MAXM],tms[MAXM][MAXM];
int read()
{int re=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();return re;
}
void print(int x,bool first)
{if(!x){if(first) putchar('0');return ;}print(x/10,false);putchar('0'+x%10);
}
void prework()
{num=pow(double(n),1.0/3.0),sz=n/num;for(int i=1;i<=num;i++) l[i]=r[i-1]+1,r[i]=sz*i;if(r[num]<n) num++,l[num]=r[num-1]+1,r[num]=n;for(int i=1;i<=num;i++)for(int j=l[i];j<=r[i];j++)belong[j]=i;sort(b+1,b+n+1);len=unique(b+1,b+n+1)-b-1;for(int i=1;i<=n;i++) c[i]=lower_bound(b+1,b+len+1,a[i])-b;for(int i=1;i<=num;i++)for(int j=i;j<=num;j++){for(int k=l[i];k<=r[j];k++) s[i][j][c[k]]++;for(int k=1;k<=len;k++)if(tms[i][j]<s[i][j][k]||(tms[i][j]==s[i][j][k]&&k<md[i][j]))md[i][j]=k,tms[i][j]=s[i][j][k];}
}
void ask(int ll,int rr)
{if(ll>rr) swap(ll,rr);int lbe=belong[ll],rbe=belong[rr],L,R;ans=cnt=0;if(rbe-lbe<=2) L=R=0;else L=lbe+1,R=rbe-1;if(L==R){for(int i=ll;i<=rr;i++){s[L][R][c[i]]++;if(cnt<s[L][R][c[i]]||(cnt==s[L][R][c[i]]&&ans>c[i]))cnt=s[L][R][c[i]],ans=c[i];}for(int i=ll;i<=rr;i++) s[L][R][c[i]]--;}else{ans=md[L][R],cnt=tms[L][R];for(int i=ll;i<=r[lbe];i++){s[L][R][c[i]]++;if(cnt<s[L][R][c[i]]||(cnt==s[L][R][c[i]]&&ans>c[i]))cnt=s[L][R][c[i]],ans=c[i];}for(int i=l[rbe];i<=rr;i++){s[L][R][c[i]]++;if(cnt<s[L][R][c[i]]||(cnt==s[L][R][c[i]]&&ans>c[i]))cnt=s[L][R][c[i]],ans=c[i];}for(int i=ll;i<=r[lbe];i++) s[L][R][c[i]]--;for(int i=l[rbe];i<=rr;i++) s[L][R][c[i]]--;}ans=b[ans];
}
int main()
{n=read(),m=read();for(int i=1;i<=n;i++) a[i]=b[i]=read();prework();while(m--){int x=(read()+ans-1)%n+1,y=(read()+ans-1)%n+1;ask(x,y);print(ans,true);putchar('\n');}return 0;
}

转载于:https://www.cnblogs.com/coder-Uranus/p/9884461.html

Luogu P4168 [Violet]蒲公英(分块)相关推荐

  1. Luogu P4168 [Violet]蒲公英 分块

    这道题算是好好写了.写了三种方法. 有一个好像是$qwq$$N\sqrt(N)$的方法,,但是恳请大佬们帮我看看为什么这么慢$qwq$(后面的第三种) 注:$pos[i]$表示$i$属于第$pos[i ...

  2. 洛谷 - P4168 [Violet]蒲公英(分块+离散化)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列,再给出 m 次查询,每次查询区间 [ l , r ] 内的众数,要求强制在线 题目分析:对于这个题意来说,如果允许离线的话,完全可以用莫队当模 ...

  3. LUOGU P4168 [Violet]蒲公英

    传送门 解题思路 分块码农题,设分成T块,cnt[i][j][k]表示第i块到第j块,k出现的次数,需要离散化.all[i][j] 表示第i块到第j块的众数.然后这两个数组先预处理出来.然后询问的时候 ...

  4. 【题解】洛谷P4168 [Violet]蒲公英 (分块)

    [题解]洛谷P4168 [Violet]蒲公英 (分块)     D e s c r i p t i o n \rm Description Description 我们把所有的蒲公英看成一个长度为 ...

  5. 洛谷 P4168 [Violet]蒲公英 解题报告

    P4168 [Violet]蒲公英 题目背景 亲爱的哥哥: 你在那个城市里面过得好吗? 我在家里面最近很开心呢.昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多 ...

  6. [luogu 4168] [Violet]蒲公英 {离散化+分块}

    题目 https://www.luogu.org/problem/P4168 解题思路 先离散化. 一个区间的最多众数显然是在中间的块或者是旁边的两个块的众数. 我们可以花O(T2n)O(T^2n)O ...

  7. 洛谷 P4168 [Violet]蒲公英

    题目:蒲公英 思路: 分块. 把所有数分成 n \sqrt{n} n ​个块,在每个块里分别求解. 代码: #include<bits/stdc++.h> using namespace ...

  8. P4168 [Violet]蒲公英

    传送门 A的第一道黑题... 然而感觉跟 作诗 没什么差别... 分块 记录 sum[ i ] [ j ] 表示从左端点到第 i 块时,数字 j 的出现次数 f [ i ] [ j ] 表示第 i 块 ...

  9. P4168 [Violet] 分块 + 二分

    题意 传送门 P4168 [Violet]蒲公英 题解 在线求区间众数问题.考虑分块,假设将整个区间分为 T T T 块,块 i i i 的边界为 [ L [ i ] , R [ i ] ) [L[i ...

最新文章

  1. 刻意练习:LeetCode实战 -- Task15. 有效的括号
  2. 又一联盟成立:清华、北大、深大、南科大、哈工大等12家在深单位加盟
  3. 《侠侣天下》资料片武魂大揭晓
  4. 数据结构 二叉树的遍历
  5. windbg网络双机内核调试
  6. laravel框架图片上传
  7. 线段树模板hdu 1754:I Hate It
  8. Python笔记-内置装饰器
  9. 中文文本相似度计算工具集
  10. 外媒:现代和起亚计划在新一代电动汽车上使用碳纳米管加热器
  11. 构建AD域 、 管理AD域
  12. VB中关于CommonDialog通用对话框的使用
  13. 《高效能人士的7个习惯》PDF,复习笔记(上)
  14. cidaemon.exe进程cpu使用率100%
  15. GD32F130之LVD低压检测
  16. 淘宝/天猫获取商品历史价格信息 API 返回值说明
  17. linux上电自动开启wifi脚本,archlinux 开机自动连接wifi
  18. 如何解决上班下午3:00发困的事情
  19. 硅谷性能服务器介绍,美国RAKsmart服务器优势特点介绍
  20. 为什么大人学英语这么难?

热门文章

  1. 从Eclipse中导入项目到AndroidStudio中
  2. 国际浏览器市场分析报告
  3. Thymeleaf是干什么的
  4. php 正则表达式 中括号 转义符能转换一个字符串吗,转义字符,正则表达式,特殊字符,模式匹配...
  5. 什么是Verilog HDL?
  6. 5月3日云栖精选夜读:乾隆会判阿尔法狗死刑吗 ——浅谈当前人工智能的技术进化...
  7. 读书笔记-《一万个小时定理》
  8. [唐诗]寻西山隐者不遇-丘为
  9. 5g网络模式是以什么划分的_5G基础知识及试题
  10. 13年毕业,用两年时间从外包走进互联网大厂!