发现写算法专题老是写不动,,,,

所以就先把我在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]蒲公英 分块的更多相关文章

  1. BZOJ2724 [Violet]蒲公英 分块

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. BZOJ2724 [Violet]蒲公英(分块)

    区间众数.分块,预处理任意两块间所有数的众数,和每块中所有数的出现次数的前缀和.查询时对不是整块的部分暴力,显然只有这里出现的数可能更新答案.于是可以优美地做到O(n√n). #include< ...

  9. p4168 [Violet]蒲公英(分块)

    区间众数的重题 和数列分块入门9双倍经验还是挺好的 然后开O2水过 好像有不带log的写法啊 之后在补就是咕咕咕 // luogu-judger-enable-o2 #include <cstd ...

随机推荐

  1. git远程版本回滚方法【转】

    step1:本地代码回滚到上一版本(或者指定版本) git reset --hard HEAD~1 step2:加入-f参数,强制提交,远程端将强制跟新到reset版本 git push -f ori ...

  2. Linux TCP/IP调优参数 /proc/sys/net/目录

    所有的TCP/IP调优参数都位于/proc/sys/net/目录. 例如, 下面是最重要的一些调优参数,后面是它们的含义: /proc/sys/net/core/rmem_default " ...

  3. 第五章Web应用与应用层协议

    Web应用与应用层协议 本篇博文中的主要参考文献是<计算机网络高级教程>,分别是吴功宜老先生和吴英教授合著.这部教程是我研究生老师所推荐的网络必读科目,由于该教程讲解的基础知识详细,但内容 ...

  4. 04-容器 What, Why, How

    What - 什么是容器? 容器是一种轻量级.可移植.自包含的软件打包技术,使应用程序可以在几乎任何地方以相同的方式运行.开发人员在自己笔记本上创建并测试好的容器,无需任何修改就能够在生产系统的虚拟机 ...

  5. docker部署war包到阿里云

    最近买了个阿里云服务器,配置1核2g内存,学习够了.记录下过程. 1,服务器相关,请看下图,云服务器主要配置是安全组和密钥,前者是开放端口,后者可以用于远程连接(比如我windows系统通过putty ...

  6. [network]交换机中用户权限

    LEVEL 0(访问级):可以执行用于网络诊断等功能的命令.包括ping.tracert.telnet等命令,执行该级别命令的结果不能被保存到配置文件中. LEVEL 1(监控级):可以执行用于系统维 ...

  7. Ztree结合jbox实现弹窗树结构

    点击添加分类,弹出事项选择框为jbox <a href="#" id="down{{row.id}}" style="display:none& ...

  8. RC电路简介,RC串并联电路的工作原理及应用

    RC电路简介,RC串并联电路的工作原理及应用 RC电路全称Resistance-Capacitance Circuits.一个 相移电路(RC电路)或称 RC滤波器. RC网络, 是一个包含利用电压源 ...

  9. scrum立会报告+燃尽图(第二周第四次)

    此作业要求参考: https://edu.cnblogs.com/campus/nenu/2018fall/homework/2249 一.小组介绍 组名:杨老师粉丝群 组长:乔静玉 组员:吴奕瑶.公 ...

  10. 路由器DMZ功能

    环境描述 172.17* 校园网 实验室路由器接入校园网,通过nat分化出网段 192.168.. 实验过程 主机A(windows)接入路由器(192.168.1.110),主机B(Ubuntu)接 ...