luogu4168蒲公英(区间众数)

给定n个数,m个区间询问,问每个询问中的众数是什么。

题面很漂亮,大家可以去看一下。

对于区间众数,由于区间的答案不能由子区间简单的找出来,所以似乎不能用树形结构。

用分块的话,设一个区间[x, y],里面包含的最大连续的块的左端点是l,右端点是r。那么显然,这个区间的众数要么是[l, r]的众数,要么是[x, l)和(r, y]中的任意数。所以可以用\(f[i][j]\)表示第i到j块的众数是什么,同时用\(s[i][x]\)表示前i个块中数x的出现次数。这样就可以做到\(n\sqrt{n}\)了。我的代码跑的算很快的。因为map没有sort快(废话)。

有一个很神的地方是f[i][j]只用保存一个值就行了,因为如果在第i个块到第j个块之间,还有数的出现次数和f[i][j]相同,那么它要超越f[i][j],必须满足在一侧的小区间中出现次数比f[i][j]多,所以它至少会在小区间中出现一次。

如果问题带修怎么办呢?还是可以用分块哟。由于我们要维护f[i][j]和s[i][j],只分\(n^{1/3}\)个块。对于某一个点上的修改,会牵动所有块。再维护cnt[i][j][k]表示i块到j块出现次数为k的数有几个即可。

#include <cmath>
#include <cctype>
#include <cstdio>
#include <algorithm>
using namespace std; const int maxn=4e4+5, sqrtm=2e2+5, INF=1e9;
int n, m, barlen, cntbar, a[maxn], bel[maxn], cnt[maxn];
int t[maxn], cntnum;
int s[sqrtm][maxn]; //前i个块x的出现次数
int f[sqrtm][sqrtm]; //第i到j块的众数是什么 void get(int &x){
x=0; char c; int flag=1;
for (c=getchar(); !isdigit(c); c=getchar());
for (x=c-48; c=getchar(), isdigit(c); )
x=x*10+c-48; x*=flag;
} int main(){
get(n); get(m); barlen=sqrt(n); cntbar=1;
for (int i=0; i<n; ++i){
get(a[i]); t[i]=a[i];
bel[i]=i/barlen;
if (i&&bel[i]!=bel[i-1]) ++cntbar;
}
sort(t, t+n); cntnum=unique(t, t+n)-t;
for (int i=0; i<n; ++i)
a[i]=lower_bound(t, t+cntnum, a[i])-t;
for (int i=0; i<n; ++i) ++s[bel[i]][a[i]];
for (int i=1; i<cntbar; ++i) //n^1.5
for (int j=0; j<n; ++j) s[i][j]+=s[i-1][j];
int maxm=0, mcnt, q1, q2, l, r, tmp;
for (int i=0; i<cntbar; ++i){ //n^1.5
for (int j=0; j<n; ++j) cnt[j]=0;
mcnt=0;
for (int j=i*barlen; j<n; ++j){
++cnt[a[j]];
if (cnt[a[j]]>mcnt||(cnt[a[j]]==mcnt&&a[j]<maxm))
mcnt=cnt[a[j]], maxm=a[j];
if (bel[j]!=bel[j+1]) f[i][bel[j]]=maxm;
}
}
maxm=0;
for (int iq=0; iq<m; ++iq){
get(q1); get(q2);
q1=(q1+maxm-1)%n; q2=(q2+maxm-1)%n; mcnt=0;
if (q1>q2) swap(q1, q2);
if (bel[q1]==bel[q2]){
maxm=INF;
for (int i=q1; i<=q2; ++i) cnt[a[i]]=0;
for (int i=q1; i<=q2; ++i){
++cnt[a[i]];
if (cnt[a[i]]>mcnt||(cnt[a[i]]==mcnt&&a[i]<maxm))
mcnt=cnt[a[i]], maxm=a[i];
}
printf("%d\n", maxm=t[maxm]);
continue;
}
l=bel[q1]+1; r=bel[q2]-1;
if (l<=r) maxm=f[l][r], mcnt=s[r][maxm]-s[l-1][maxm];
//cnt表示两边需要暴力查找的数的出现个数
for (int i=q1; i==q1||bel[i]==bel[i-1]; ++i) cnt[a[i]]=0;
for (int i=q2; i==q2||bel[i]==bel[i+1]; --i) cnt[a[i]]=0;
for (int i=q1; i==q1||bel[i]==bel[i-1]; ++i) ++cnt[a[i]];
for (int i=q2; i==q2||bel[i]==bel[i+1]; --i) ++cnt[a[i]];
for (int i=q1; i==q1||bel[i]==bel[i-1]; ++i){
tmp=cnt[a[i]]+s[r][a[i]]-s[l-1][a[i]];
if (tmp>mcnt||(tmp==mcnt&&a[i]<maxm))
mcnt=tmp, maxm=a[i];
}
for (int i=q2; i==q2||bel[i]==bel[i+1]; --i){
tmp=cnt[a[i]]+s[r][a[i]]-s[l-1][a[i]];
if (tmp>mcnt||(tmp==mcnt&&a[i]<maxm))
mcnt=tmp, maxm=a[i];
}
printf("%d\n", maxm=t[maxm]);
}
return 0;
}

luogu4168蒲公英(区间众数)的更多相关文章

  1. P4168 [Violet]蒲公英 区间众数

    $ \color{#0066ff}{ 题目描述 }$ 在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关. 为了简化起见,我们把所有的蒲公英看成一个长度为n的序列 \((a_1,a_2.. ...

  2. 【BZOJ 2724】 2724: [Violet 6]蒲公英 (区间众数不带修改版本)

    2724: [Violet 6]蒲公英 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1908  Solved: 678 Description In ...

  3. 洛谷P4168 蒲公英 分块处理区间众数模板

    题面. 许久以前我还不怎么去机房的时候,一位大佬好像一直在做这道题,他称这道题目为"大分块". 其实这道题目的思想不只可以用于处理区间众数,还可以处理很多区间数值相关问题. 让我们 ...

  4. 蒲公英(bzoj2724)(分块+区间众数)

    Input Output Sample Input 6 3 1 2 3 2 1 2 1 5 3 6 1 5 Sample Output 1 2 1 HINT \(n <= 40000\),$ m ...

  5. Luogu4168 蒲公英 (分块)

    题目传送门 题意 长度为n的序列,有m次询问,每次询问求\([l,r]\) 间的众数,如果有多个,输出最小的那个 \(n\le 4\times 10^4,m\le 5\times 10^5,a_i\l ...

  6. BZOJ 2724: [Violet 6]蒲公英 [分块 区间众数]

    传送门 题面太美不忍不放 分块分块 这种题的一个特点是只有查询,通常需要预处理:加入修改的话需要暴力重构预处理 预处理$f[i][j]$为第i块到第j块的众数,显然$f[i][j]=max{f[i][ ...

  7. bzoj2724: [Violet 6]蒲公英 分块 区间众数 论algorithm与vector的正确打开方式

    这个,要处理各个数的话得先离散,我用的桶. 我们先把每个块里的和每个块区间的众数找出来,那么在查询的时候,可能成为[l,r]区间的众数的数只有中间区间的众数和两边的数. 证明:若不是这里的数连区间的众 ...

  8. 【luogu1468】[Violet]蒲公英--求区间众数

    题目背景 亲爱的哥哥: 你在那个城市里面过得好吗? 我在家里面最近很开心呢.昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了.我觉得把那么可怕 ...

  9. 【BZOJ2724】蒲公英 题解(分块+区间众数)

    题目链接 题目大意:给定一段长度为$n$的序列和$m$次询问,每次询问区间$[l,r]$内的最小的众数.$n\leq 40000,a_i\leq 10^9$ --------------------- ...

随机推荐

  1. linux应用之yum命令的软件源的更换(centos)

    [1] 首先备份/etc/yum.repos.d/CentOS-Base.repo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/Cent ...

  2. python习题-用交集方式产生随机密码

    # 1.写一个产生密码的程序,# 输入次数,输入多少次就产生多少条数据,# 要求密码必须包含大写字母.小写字母和数字,长度8位,不能重复 import string ,random num=input ...

  3. linux命令学习笔记(59):rcp命令

    rcp代表“remote file copy”(远程文件拷贝).该命令用于在计算机之间拷贝文件.rcp命令有两种格式.第一种格式用于文件到文件的拷贝:第二种格式用于把文件或目录拷贝到另一个目录中. . ...

  4. 如果你使用WebView+FloatingActionButton

    在WebView中想要使用FAB,如果你想向上滑动的时候隐藏FAB,那么需要再WebView外面套一个ScrollView! 原因之前也分析过,和为什么ListView不能让ToolBar.Tab隐藏 ...

  5. ACM学习历程—BNUOJ3685 Building for UN(构造)

    The United Nations has decided to build a new headquarters in Saint Petersburg, Russia. It will have ...

  6. unity中mesh属性的uv坐标讨论

    http://blog.sina.com.cn/s/blog_427cf00b0102vp0j.html 之前在做连连看游戏中,也用到贴图坐标,当时我们讲到,不管是平铺(Tiling)还是偏移(Off ...

  7. hdu 5909 Tree Cutting —— 点分治

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治,每次的 rt 是必选的点: 考虑必须选根的一个连通块,可以DP,决策就是在每个子树中决定选不 ...

  8. Sublime 实践

    1.下载开发版:http://www.sublimetext.com/dev 2.安装Package control: (1)按键ctrl+~ (2)在命令行中输入:  import urllib2, ...

  9. js中的setInterval

    跟几个例子吧 计时器的例子: /** * Created by Administrator on 2016/8/5. */ (function () { function show() { var t ...

  10. Redis的安装和配置文件

    实验环境:Centos6.8 Redis版本:3.0.6 下载Redis,并放到/usr/local/soft下: yum -y install gcc automake autoconf libto ...