bzoj2724: [Violet 6]蒲公英(离散化+分块)
我好弱啊。。这题调了2天QwQ
题目大意:给定一个长度为n(n<=40000)的序列,m(m<=50000)次询问l~r之间出现次数最多的数。(区间众数)
这题如果用主席树就可以不用处理一堆前缀和。。蓝鹅我不会~T_T~
把序列n分成sqrt(n)块,先把所有数离散化,预处理出poi[i][j]表示第i块到第j块的众数(即出现次数最多的数)。
询问有两种情况:
第一种情况是l~r在某个块中,那么直接扫一遍求出众数,效率O(sqrt(n))。
第二种情况是l~r在多个块中,l在x块,r在y块,那么我们可以把它分为三部分:①l~x块最后一个数②x+1块~y-1块③y块第一个数~r。
因为我们求出了poi数组,所以我们可以知道第二部分的众数,显然我们只要统计一下第一部分、第三部分每个数出现的次数,将它们和第二部分的众数出现的次数进行比较,出现次数最多的数就是l~r的众数。
而第一部分、第三部分数的个数不超过2*sqrtn(n)个,所以扫一遍第一部分、第三部分的数,效率O(sqrt(n)),问题就是怎么O(1)求出第一部分、第三部分的每个数在l~r出现的次数了。如果是O(1),那么可以想到的就是前缀和,于是我们再预处理出qzh[i][a]表示前i块中a出现的次数,qzh2[i][j][a]表示第i块前j个数中a出现的次数。那么设第一部分某个数为a,l在x块,r在y块,它在l~r中出现的次数就是:
qzh[y-1][a]-qzh[x-1][a]-qzh2[x][(l-1)%sqrtn==0?sqrtn:(l-1)%sqrtn][a]
+qzh2[x][(r-1)%sqrtn+1==sqrtn?0:(r-1)%sqrtn+1][a]
【写的好丑哇QAAAAQ
第三部分同理,然后和第二部分预处理出来的众数在l~r出现的次数(求法同理)比较找出最大的就行了。
预处理O(nsqrt(n)),询问O(qsqrt(n)),总的时间复杂度O((n+q)sqrt(n))。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
map<int,int>M[];
struct zs{int num,pos;}b[];
int n,m,l,r,cnt,ans,poi[][],a[],pos[],sum[],qzh[][],qzh2[][][],num[],ppos[][];
bool v[];
bool cmp(zs a,zs b){return a.num<b.num;}
int main()
{
scanf("%d %d",&n,&m);
int sqrtn=(int)ceil(sqrt(n));
for(int i=;i<=n;i++)scanf("%d",&a[i]),b[i].num=a[i],b[i].pos=i;
sort(b+,b++n,cmp);
for(int i=;i<=n;i++)
{
if(b[i].num!=b[i-].num)cnt++;
pos[b[i].pos]=cnt;
}
for(int i=;i<=sqrtn;i++)
for(int j=;j<=sqrtn;j++)
{
if((i-)*sqrtn+j<=n)if(M[i].find(a[(i-)*sqrtn+j])==M[i].end())
M[i][a[(i-)*sqrtn+j]]=++num[i];
ppos[i][pos[(i-)*sqrtn+j]]=M[i][a[(i-)*sqrtn+j]];
}
for(int i=;i<=n;i++)qzh[((i-)/sqrtn)+][pos[i]]++;
for(int i=;i<=n;i++)for(int j=;j<=sqrtn;j++)qzh[j][i]+=qzh[j-][i];
for(int i=;i<=sqrtn;i++)for(int j=;j<=sqrtn;j++)if((i-)*sqrtn+j<=n)qzh2[i][j][ppos[i][pos[(i-)*sqrtn+j]]]++;
for(int i=;i<=sqrtn;i++)
{
for(int k=;k<=sqrtn;k++)if((i-)*sqrtn+k<=n)v[pos[(i-)*sqrtn+k]]=;
for(int k=;k<=sqrtn;k++)
if((i-)*sqrtn+k<=n)
if(!v[pos[(i-)*sqrtn+k]])
{
for(int j=;j<=sqrtn;j++)
if((i-)*sqrtn+j<=n)qzh2[i][j][ppos[i][pos[(i-)*sqrtn+k]]]+=qzh2[i][j-][ppos[i][pos[(i-)*sqrtn+k]]];
v[pos[(i-)*sqrtn+k]]=;
}
}
for(int i=;i<=sqrtn;i++)
{
memset(sum,,sizeof(sum));
int max=,maxi=;
for(int j=i;j<=sqrtn;j++)
{
for(int k=;k<=sqrtn;k++)
{
int x=(j-)*sqrtn+k;
if(x>n)break;
if(++sum[pos[x]]>max||((sum[pos[x]]==max)&&(pos[x]<pos[maxi])))max=sum[pos[x]],maxi=x;
}
poi[i][j]=maxi;
}
}
for(int i=;i<=m;i++)
{
scanf("%d %d",&l,&r);
l=(l+ans-)%n+;r=(r+ans-)%n+;if(r<l)swap(l,r);
if((int)ceil(r/sqrtn)==(int)ceil(l/sqrtn))
{
int maxx=,maxi=;
memset(sum,,sizeof(sum));
for(int j=l;j<=r;j++)
if(++sum[pos[j]]>maxx||((sum[pos[j]]==maxx)&&(pos[j]<pos[maxi])))maxx=sum[pos[j]],maxi=j;
ans=a[maxi];
printf("%d\n",a[maxi]);
}else
{
int ll=-,rr=;
for(int j=;j<=sqrtn;j++)
{
if(j*sqrtn+>=l&&(ll==-))ll=j*sqrtn;
if(j*sqrtn<=r)rr=j*sqrtn;
}
int y=poi[ll/sqrtn+][rr/sqrtn];
for(int j=l;j<=ll;j++)
{
int lll=y;
int x=qzh[rr/sqrtn][pos[j]]-qzh[max(ll/sqrtn-,)][pos[j]]-qzh2[ll/sqrtn][(l-)%sqrtn==?sqrtn:(l-)%sqrtn][ppos[ll/sqrtn][pos[j]]]+qzh2[rr/sqrtn+][(r-)%sqrtn+==sqrtn?:(r-)%sqrtn+][ppos[rr/sqrtn+][pos[j]]];
y=qzh[rr/sqrtn][pos[lll]]-qzh[max(ll/sqrtn-,)][pos[lll]]-qzh2[ll/sqrtn][(l-)%sqrtn==?sqrtn:(l-)%sqrtn][ppos[ll/sqrtn][pos[lll]]]+qzh2[rr/sqrtn+][(r-)%sqrtn+==sqrtn?:(r-)%sqrtn+][ppos[rr/sqrtn+][pos[lll]]];
if(x>y||((x==y)&&pos[j]<pos[lll]))y=j;else y=lll;
}
for(int j=rr+;j<=r;j++)
{
int lll=y;
int x=qzh[rr/sqrtn][pos[j]]-qzh[max(ll/sqrtn-,)][pos[j]]-qzh2[ll/sqrtn][(l-)%sqrtn==?sqrtn:(l-)%sqrtn][ppos[ll/sqrtn][pos[j]]]+qzh2[rr/sqrtn+][(r-)%sqrtn+==sqrtn?:(r-)%sqrtn+][ppos[rr/sqrtn+][pos[j]]];
y=qzh[rr/sqrtn][pos[lll]]-qzh[max(ll/sqrtn-,)][pos[lll]]-qzh2[ll/sqrtn][(l-)%sqrtn==?sqrtn:(l-)%sqrtn][ppos[ll/sqrtn][pos[lll]]]+qzh2[rr/sqrtn+][(r-)%sqrtn+==sqrtn?:(r-)%sqrtn+][ppos[rr/sqrtn+][pos[lll]]];
if(x>y||((x==y)&&pos[j]<pos[lll]))y=j;else y=lll;
}
printf("%d\n",a[y]);ans=a[y];
}
}
}
bzoj2724: [Violet 6]蒲公英(离散化+分块)的更多相关文章
- bzoj2724: [Violet 6]蒲公英(分块)
传送门 md调了一个晚上最后发现竟然是空间开小了……明明算出来够的…… 讲真其实我以前不太瞧得起分块,觉得这种基于暴力的数据结构一点美感都没有.然而今天做了这道分块的题才发现分块的暴力之美(如果我空间 ...
- [BZOJ2724][Violet 6]蒲公英
[BZOJ2724][Violet 6]蒲公英 试题描述 输入 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1 输出 输入示 ...
- BZOJ_2724_[Violet 6]蒲公英_分块
BZOJ_2724_[Violet 6]蒲公英_分块 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod ...
- BZOJ2724 [Violet 6]蒲公英 分块
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2724.html 题目传送门 - BZOJ2724 题意 求区间最小众数,强制在线. $n$ 个数,$m ...
- 【分块】bzoj2724 [Violet 6]蒲公英
分块,离散化,预处理出: ①前i块中x出现的次数(差分): ②第i块到第j块中的众数是谁,出现了多少次. 询问的时候,对于整块的部分直接获得答案:对于零散的部分,暴力统计每个数出现的次数,加上差分的结 ...
- bzoj2724: [Violet 6]蒲公英 分块 区间众数 论algorithm与vector的正确打开方式
这个,要处理各个数的话得先离散,我用的桶. 我们先把每个块里的和每个块区间的众数找出来,那么在查询的时候,可能成为[l,r]区间的众数的数只有中间区间的众数和两边的数. 证明:若不是这里的数连区间的众 ...
- BZOJ.2724.[Violet 6]蒲公英(静态分块)
题目链接 区间众数 强制在线 考虑什么样的数会成为众数 如果一个区间S1的众数为x,那么S1与新区间S2的并的众数只会是x或S2中的数 所以我们可以分块先预处理f[i][j]表示第i到第j块的众数 对 ...
- [BZOJ 2724] [Violet 6] 蒲公英 【分块】
题目链接:BZOJ - 2724 题目分析 这道题和 BZOJ-2821 作诗 那道题几乎是一样的,就是直接分块,每块大小 sqrt(n) ,然后将数字按照数值为第一关键字,位置为第二关键字排序,方便 ...
- 【BZOJ2724】[Violet 6]蒲公英 分块+二分
[BZOJ2724][Violet 6]蒲公英 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n ...
随机推荐
- Allure--自动化测试报告生成
之前尝试使用过testNG自带的测试报告.优化过reportNG的测试报告,对这两个报告都不能满意.后经查找资料,发现有个神器: Allure(已经有allure2了,笔者使用的就是allure2), ...
- 小程序button 去边框
/*使用 button::after{ border: none; } 来去除边框*/.free-btn-bordernone{ background: none !important; color: ...
- 微信小程序之基础案例详细解释
这是案例的初始页面 首先关于这个案例上面的app.json做一个特别详细的解释 首先提醒一下.json文件不能有注释,因此如果要复制的话,请把注释删去 //关于app.json详细学习 { //pag ...
- Django学习总结- ③
对象属性与继承关系: 对象属性 1. 显示属性 - 开发者手动定义的,直接看的到的 2. 隐式属性 - 系统根据需求,自动创建的对象 - objects 它是model.Manager对象 - 当我们 ...
- 技本功丨知否知否,Redux源码竟如此意味深长(上集)
夫 子 说 元月二号欠下袋鼠云技术公号一篇关于Redux源码解读的文章,转眼月底,期间常被“债主”上门催债.由于年底项目工期比较紧,于是债务就这样被利滚利.但是好在这段时间有点闲暇,于是赶紧把这篇文章 ...
- 从零开始的Python学习Episode 2——运算符与while循环
一.算术运算符 加法:+,减法:-,乘法*,除法/,整除(地板除)//,取余%,乘方**. 二.逻辑运算符 且:and,或:or,非:not 优先级:not>and>or 短路原则: 对 ...
- springMVC第二章
springMVC第二章 一.URL 映射 可以同时设置多个URL来访问某个控制器或方法.设置value属性: @RequestMapping(value= {"/grade",& ...
- 150命令之线上查询及帮助命令 man hellp
150命令之线上查询及帮助命令 man 查询命令的帮助 man + 命令 NAME ls - list directory contents 命令+命令简单说明 SYNOPSIS ...
- POJ 2826 An Easy Problem?!(线段交点+简单计算)
Description It's raining outside. Farmer Johnson's bull Ben wants some rain to water his flowers. Be ...
- Linux上安装MySQL - 12条命令搞定MySql
从零开始安装mysql数据库 : 按照该顺序执行 : a. 查看是否安装有mysql:yum list installed mysql*, 如果有先卸载掉, 然后在进行安装; b. 安装mysql客 ...