【BZOJ2724】蒲公英(分块)

题面

洛谷

谴责权限题的行为

题解

分块什么的都不会,根本就没写过几次。

复杂度根本不会分析,吓得我赶快来练练。

这题要求的是区间众数,显然没有什么很好的主席树之类的方法。

再加之这个数据范围很像\(O(n\sqrt n)\),所以我们来分块,假设块大小为\(\sqrt n\)。

首先颜色什么的直接离散是没有任何问题的。

那么我们可以考虑分块之后对于每一个颜色在块内的出现次数维护一个前缀和,但是这样子仍然无法快速得出一个颜色在某特定区间的出现次数。所以我们对于每一个颜色维护一个\(vector\),把所有出现的位置按照顺序压进来,这样子每次二分即可。

考虑区间众数是怎么产生的,要么是中间连续整块的众数,要么是区间左右两侧非整块的区间中出现过的数字。

中间连续整块的众数可以预处理,设\(g[i][j]\)表示第\(i\)块到第\(j\)块的众数,显然这个可以固定左端点,然后向右端点推进预处理结果。

对于非整块区间出现的位置,因为最多只会有\(2\sqrt n\)个,所以可以对于每一个数字暴力二分一遍,这样子的复杂度是\(O(\sqrt nlogn)\)的。

看起来复杂度就很对了?\(O(n\sqrt n logn)\),似乎块大小不取\(\sqrt n\)而是取别的值的时候更优秀。(尝试了一堆值,从\(200\)取到了\(20\),发现取\(30\)的时候最优)

我代码常数比较大。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 40040
const int m=30;
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,Q,blk,a[MAX],b[MAX];
int S[MAX],tot,num[MAX];
vector<int> p[MAX];
int f[1500][1500];
int Calc(int x,int l,int r)
{
if(p[x].size()==0)return 0;
int L,R,ret1,ret2;
L=0,R=p[x].size()-1,ret1=R;
while(L<=R)
{
int mid=(L+R)>>1;
if(p[x][mid]>=l)ret1=mid,R=mid-1;
else L=mid+1;
}
L=0,R=p[x].size()-1,ret2=L;
while(L<=R)
{
int mid=(L+R)>>1;
if(p[x][mid]<=r)ret2=mid,L=mid+1;
else R=mid-1;
}
return max(ret2-ret1+1,0);
}
int main()
{
n=read();Q=read();blk=(n+m-1)/m;
for(int i=1;i<=n;++i)S[i]=a[i]=read();
sort(&S[1],&S[n+1]);tot=unique(&S[1],&S[n+1])-S-1;
for(int i=1;i<=n;++i)a[i]=lower_bound(&S[1],&S[tot+1],a[i])-S;
for(int i=1;i<=n;++i)p[a[i]].push_back(i);
for(int i=1;i<=n;++i)b[i]=(i-1)/m+1;
for(int i=1;i<=blk;++i)
{
memset(num,0,sizeof(num));
int x=0;
for(int k=i;k<=blk;++k)
{
for(int j=(k-1)*m+1;j<=n&&j<=k*m;++j)
{
num[a[j]]++;
if(num[a[j]]>num[x]||(num[a[j]]==num[x]&&x>a[j]))x=a[j];
}
f[i][k]=x;
}
}
int ans=0;
while(Q--)
{
int l=(read()+ans-1)%n+1,r=(read()+ans-1)%n+1;
if(l>r)swap(l,r);
int mx=0,x=0;
if(b[l]==b[r])
for(int i=l;i<=r;++i)
{
int d=Calc(a[i],l,r);
if(d>mx||(d==mx&&x>a[i]))mx=d,x=a[i];
}
else
{
x=f[b[l]+1][b[r]-1];mx=Calc(x,l,r);
for(int i=l;i<=n&&(i==l||i%m!=1);++i)
{
int d=Calc(a[i],l,r);
if(d>mx||(d==mx&&x>a[i]))mx=d,x=a[i];
}
for(int i=r;i>=1&&(i==r||i%m!=0);--i)
{
int d=Calc(a[i],l,r);
if(d>mx||(d==mx&&x>a[i]))mx=d,x=a[i];
}
}
printf("%d\n",ans=S[x]);
}
return 0;
}

【BZOJ2724】蒲公英(分块)的更多相关文章

  1. [日常摸鱼]bzoj2724蒲公英-分块

    区间众数经典题~ http://begin.lydsy.com/JudgeOnline/problem.php?id=4839这里可以提交~ 题意大概就是没有修改的询问区间众数,如果有一样的输出最小的 ...

  2. BZOJ2724 蒲公英 【分块】

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

  3. 【BZOJ2724】[Violet 6]蒲公英 分块+二分

    [BZOJ2724][Violet 6]蒲公英 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n ...

  4. BZOJ2724 [Violet 6]蒲公英 分块

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2724.html 题目传送门 - BZOJ2724 题意 求区间最小众数,强制在线. $n$ 个数,$m ...

  5. 【bzoj2724】[Violet 6]蒲公英 分块+STL-vector

    题目描述 输入 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1 输出 样例输入 6 3 1 2 3 2 1 2 1 5 3 ...

  6. BZOJ2724 [Violet]蒲公英 分块

    题目描述 经典区间众数题目 然而是权限题,所以题目链接放Luogu的 题解 因为太菜所以只会$O(n*\sqrt{n}+n*\sqrt{n}*log(n))$的做法 就是那种要用二分的,并不会clj那 ...

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

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

  8. BZOJ 2724: [Violet 6]蒲公英( 分块 )

    虽然AC了但是时间惨不忍睹...不科学....怎么会那么慢呢... 无修改的区间众数..分块, 预处理出Mode[i][j]表示第i块到第j块的众数, sum[i][j]表示前i块j出现次数(前缀和, ...

  9. [Violet]蒲公英 分块

    发现写算法专题老是写不动,,,, 所以就先把我在luogu上的题解搬过来吧! 题目大意:查询区间众数,无修改,强制在线 乍一看是一道恐怖的题,仔细一看发现并没有那么难: 大致思路是这样的,首先我们要充 ...

  10. [BZOJ2724] 蒲公英

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

随机推荐

  1. Python之Django基本命令

    一.新建项目 $django-admin.py startproject project_name # 特别是在 windows 上,如果报错,尝试用 django-admin 代替 django-a ...

  2. Halcon四 双目视觉的标定

    原文作者写的一系列博客,挺不错的学习halcon:http://blog.sina.com.cn/s/blog_442bfe0e0100yjtn.html 1.get_image_pointer1(I ...

  3. Halcon中循环的相关算子

    条件<condition> ,<condition> 内为计算成an integer or boolean value的表达式. 表达式的值1则条件为真,否则为假. 1.if( ...

  4. Python中格式化format()方法详解

    Python中格式化format()方法详解 Python中格式化输出字符串使用format()函数, 字符串即类, 可以使用方法; Python是完全面向对象的语言, 任何东西都是对象; 字符串的参 ...

  5. linux-shell-screen后台调用-后台运行脚本和命令-仿start命令-伪窗口界面

    序 我比较熟练bat.cmd脚本.刚接触使用shell时,总会习惯想用windows窗口界面来套用shell脚本.于是找到screen后台命令,它可以交互shell脚本,保持后台运行.但是在批处理ba ...

  6. PytorchZerotoAll学习笔记(一)

    Pytorch的安装请参考torch的官方文档,传送门:https://pytorch.org/get-started/locally/ Numpy的复习 如果你之前没有学过Numpy的话,建议去看看 ...

  7. linux后台启动程序脚本实例

    启动安装的zookeeper和kafka #!/bin/bash # start zookeeper and kafka service echo "========== Start the ...

  8. Django_rest_framework_版本(待验证)

    简介 API版本控制可以用来在不同的客户端使用不同的行为.REST框架提供了大量不同的版本设计. 版本控制是由传入的客户端请求决定的,并且可能基于请求URL,或者基于请求头. 有许多有效的方法达到版本 ...

  9. 2017年软件工程作业-“Hello World!”团队互评beta版本

    A.欢迎来怼——博客园安卓APP(测评人:刘淑霞) 博客地址:http://www.cnblogs.com/liusx0303/p/7905928.html B.Thunder——爱阅app(测评人: ...

  10. “Hello World!”团队第六周第六次会议

    “Hello World!”团队第六周第六次会议   博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 八.checkout& ...