[Violet]蒲公英 分块
发现写算法专题老是写不动,,,,
所以就先把我在luogu上的题解搬过来吧!
题目大意:查询区间众数,无修改,强制在线
乍一看是一道恐怖的题,仔细一看发现并没有那么难;
大致思路是这样的,首先我们要充分发挥分块暴力大法好的精神
先暴力预处理出每个块内每种蒲公英的个数,
然后求出对每个块而言的前缀和,
于是这样我们就可以区间查询任意两个块之间每种蒲公英的数量了
然后我们预处理出任意两个块之间的众数
最后对于每组询问,我们先找到夹在它们中间的块,
如果这个两个块r-l<=1,那么我们暴力求众数
为什么? 因为不这样的话,万一x,y在一个快,那么r可能会比l小,要特判
如果x,y隔得很近,同样有各种奇奇怪怪的情况要做特判,
那既然这么麻烦,我们不如直接暴力搞是吧。
如果两个块相差超过了1,那么我们先取出中间块的众数,作为我们的answer,然后对旁边两个块暴力处理众数(此处注意判断时要加上中间的蒲公英)。
最后我们就得到了答案,
但是注意到ai的范围很大,所以我们需要离散化。
并且由于数量相同时要优先编号小的,于是我们处理众数的时候要多加这个判断
基本就是这样了。。。
表示本蒟蒻一A过了还是很开心的(^▽^)(虽然说第一次交没删调试结果too many or too few lines 了,但是去掉调试就过了,也可以算是一A嘛是吧)
下面代码:
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 40100
#define ac 210
#define D printf("line in %d\n",__LINE__);
int block,n,m,answer,tot;
int s[AC];
struct abc{
int num,w,x;
}b[AC];//原数列+离散化后数组
int sum[ac][AC];//每种数字块内前缀和
int ans[ac][ac];//任意两块之间的众数
int belong[AC];//所属块
int color[AC]; inline int read()
{
int x=;char c=getchar();
while(c>'' || c<'') c=getchar();
while(c>='' && c<='') x=x*+c-'',c=getchar();
return x;
} bool cmp1(abc a,abc b)
{
return a.w < b.w;
} bool cmp2(abc a,abc b)
{
return a.num < b.num;
} void search(int x,int y)
{
// printf("%d %d\n",x,y);
int l=x/block + ,r=y/block - ;//取出中间块
if(r - l <= )//如果x,y相差很小,那么暴力统计
{
answer=;
for(R i=x;i<=y;i++)
if((++color[b[i].x] > color[answer]) || (color[b[i].x] == color[answer] && b[i].x < answer)) answer=b[i].x;
for(R i=x;i<=y;i++)
--color[b[i].x];
printf("%d\n",s[answer]);
return ;
}
else//不然的话
{
int ll=l * block - ,rr=(r+) * block;
answer=ans[l][r];
for(R i=x;i<=ll;i++)
{
++color[b[i].x];
if(color[b[i].x] + sum[r][b[i].x] - sum[l-][b[i].x] > color[answer] + sum[r][answer] - sum[l-][answer]) answer=b[i].x;
else if(color[b[i].x] + sum[r][b[i].x] - sum[l-][b[i].x] == color[answer] + sum[r][answer] - sum[l-][answer] && b[i].x < answer) answer=b[i].x;//编号小也要优先,因为一行写不下,为了美观,,,就用else吧,不然就用||了
}
for(R i=rr;i<=y;i++)
{
++color[b[i].x];
if(color[b[i].x] + sum[r][b[i].x] - sum[l-][b[i].x] > color[answer] + sum[r][answer] - sum[l-][answer]) answer=b[i].x;
else if(color[b[i].x] + sum[r][b[i].x] - sum[l-][b[i].x] == color[answer] + sum[r][answer] - sum[l-][answer] && b[i].x < answer) answer=b[i].x;
}
for(R i=x;i<=ll;i++) --color[b[i].x];
for(R i=rr;i<=y;i++) --color[b[i].x];
printf("%d\n",s[answer]);
return ;
}
} void pre()//读入
{
n=read(),m=read();
block=sqrt(n);
for(R i=;i<=n;i++) b[i].w=read(),b[i].num=i;
sort(b+,b+n+,cmp1);
for(R i=;i<=n;i++)
{
if(b[i].w != b[i-].w)
{
s[++tot]=b[i].w;//存下对应新编号的对应真实编号
b[i].x=tot;
}
else b[i].x=b[i-].x;//离散化
}
sort(b+,b+n+,cmp2);
} void getsum()
{//注意0也被分在块0中
for(R i=;i<=n;i++)
{
belong[i]=i/block;
sum[belong[i]][b[i].x]++;
}
for(R i=;i<=belong[n];i++)
for(R j=;j<=tot;j++)
sum[i][j]+=sum[i-][j];
} void getans()
{
for(R i=;i<=belong[n];i++)
{
int be=i * block,now=;
if(!be) be=;//这里和作诗不同,因为这里的now要参与比较了,而不是单纯的统计,而now初始值为0,所以color[0]不能被修改
for(R j=be;j<=n;j++)
{
if((++color[b[j].x] > color[now]) || (color[b[j].x] == color[now] && b[j].x < now)) now=b[j].x;//更新ans
ans[i][belong[j]]=now;//存下新ans
}
for(R j=be;j<=n;j++) --color[b[j].x];//暴力撤销
}
/*for(R i=0;i<=belong[n];i++)
{
for(R j=i;j<=belong[n];j++)
printf("%d ",ans[i][j]);
printf("\n");
}*/
} void work()//预处理出前缀和和众数
{
int a,b;
for(R i=;i<=m;i++)
{
a=(read() + s[answer] -) % n + ,b=(read() + s[answer] - ) % n + ;//获取询问
if(a < b) search(a,b);
else search(b,a);//因为经过了运算,所以大小顺序就可能改变了
}
} int main()
{
// freopen("in.in","r",stdin);
pre();
getsum();
getans();
work();
// fclose(stdin);
return ;
}
[Violet]蒲公英 分块的更多相关文章
- BZOJ2724 [Violet]蒲公英 分块
题目描述 经典区间众数题目 然而是权限题,所以题目链接放Luogu的 题解 因为太菜所以只会$O(n*\sqrt{n}+n*\sqrt{n}*log(n))$的做法 就是那种要用二分的,并不会clj那 ...
- Luogu P4168 [Violet]蒲公英 分块
这道题算是好好写了.写了三种方法. 有一个好像是$qwq$$N\sqrt(N)$的方法,,但是恳请大佬们帮我看看为什么这么慢$qwq$(后面的第三种) 注:$pos[i]$表示$i$属于第$pos[i ...
- 洛谷 P4168 [Violet]蒲公英 解题报告
P4168 [Violet]蒲公英 题目背景 亲爱的哥哥: 你在那个城市里面过得好吗? 我在家里面最近很开心呢.昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多 ...
- BZOJ 2724: [Violet 6]蒲公英( 分块 )
虽然AC了但是时间惨不忍睹...不科学....怎么会那么慢呢... 无修改的区间众数..分块, 预处理出Mode[i][j]表示第i块到第j块的众数, sum[i][j]表示前i块j出现次数(前缀和, ...
- 【BZOJ2724】[Violet 6]蒲公英 分块+二分
[BZOJ2724][Violet 6]蒲公英 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n ...
- BZOJ 2724: [Violet 6]蒲公英 [分块 区间众数]
传送门 题面太美不忍不放 分块分块 这种题的一个特点是只有查询,通常需要预处理:加入修改的话需要暴力重构预处理 预处理$f[i][j]$为第i块到第j块的众数,显然$f[i][j]=max{f[i][ ...
- BZOJ2724 [Violet 6]蒲公英 分块
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2724.html 题目传送门 - BZOJ2724 题意 求区间最小众数,强制在线. $n$ 个数,$m ...
- BZOJ2724 [Violet]蒲公英(分块)
区间众数.分块,预处理任意两块间所有数的众数,和每块中所有数的出现次数的前缀和.查询时对不是整块的部分暴力,显然只有这里出现的数可能更新答案.于是可以优美地做到O(n√n). #include< ...
- p4168 [Violet]蒲公英(分块)
区间众数的重题 和数列分块入门9双倍经验还是挺好的 然后开O2水过 好像有不带log的写法啊 之后在补就是咕咕咕 // luogu-judger-enable-o2 #include <cstd ...
随机推荐
- 写一个 setter 方法用于完成 @property (nonatomic, retain) NSString *name,
写一个 setter 方法用于完成 @property (nonatomic, retain) NSString *name 写一个 setter 方法用于完成 @property (nonatomi ...
- Spring Boot 整合JDBC 实现后端项目开发
一.前言 二.新建Spring Boot 项目 三.Spring Boot 整合JDBC 与MySQL 交互 3.1 新建数据表skr_user 3.2 Jdbcproject 项目结构如下 3.3 ...
- 换Mac了,迈入了终端的大门
多终端其实本质和多线程一样,所有终端其实都共享着同一个内存只不过不同终端对共享内存不同部分的权限不同罢了所以对终端的数量必须要有限制 我这里开启了四个线程,很明显四个线程都在跑同一个内存而且四个线程都 ...
- PHPCMS V9 的手机门户wap绑定单页面
当前的Phpcms V9手机网站的设置还有点弱,绑定的栏目不能设置选择模板,而且不能绑定单页面page.不过可以自定义做到绑定单页面page这一个功能:1.修改phpcms\modules\wap\i ...
- 【坚持】Selenium+Python学习之从读懂代码开始 DAY1
学习Selenium+Python已经好几个月了,但越学发现不懂的东西越多. 感觉最大的问题还是在于基础不扎实,决定从头开始,每天坚持读代码,写代码. 相信量变一定能到质变!!! 2018/05/09 ...
- springMVC 第一章
springMVC 第一章 一.分层结构的项目 组成方式: 表示层:页面,Servlet 业务层:业务逻辑类(service) 持久层:与数据库交互的类(dao) 程序执行的过程:表示层->se ...
- Pyhone学习之环境搭建
一.python 环境搭建 本章节我们将向大家介绍如何在本地搭建Python开发环境.Python可应用于多平台包括 Linux 和 Mac OS X.你可以通过终端窗口输入 "python ...
- 微软职位内部推荐-Senior Software Engineer II-Sharepoint
微软近期Open的职位: SharePoint is a multi-billion dollar enterprise business that has grown from an on-prem ...
- IT工具使用
linux 其他知识目录 常用快捷键总结 博客view code 删除,先删除,再清除格式
- ORA-28000: the account is locked 查哪个具体ip地址造成
查系统默认的策略,连续验证10次错误帐户即会被锁 SQL> select resource_name, limit from dba_profiles where profile='DEFAUL ...