嘟嘟嘟

分块经典题竟然是一道黑题……

分块求区间众数的大体思想是对于询问区间[L, R],预处理出这中间的整块的众数,然后统计两边零散的数在[L, R]中出现的次数,最后取出现次数最多且最小的数。

因此需要一个sum[i][j]表示前 i 块中数字 j 出现的次数,ans[i][j]表示块 i 到 j 的众数。预处理sum用前缀和的思想,O(n√n)可完成。预处理ans就是枚举左端点是第几个块,然后每一次从这个块的左端点O(n)扫一遍,复杂度也是O(n√n)。

查询的时候,整块的众数即其个数分别是pos = ans[l + 1][r - 1],Max = sum[r - 1][pos] - sum[l][pos]。然后零散的数我们单独开一个数组记录一下,同时记录他在零三部分出现的次数num[i],这样这个数在[L, R]中出现的次数就是sum[r - 1][x] - sum[l][x] + num[x]。最后比较取大。

本题ai较大,所以要离散化,这并不影响众数。

采纳lba大佬的意见,为了避免重复运算从而降低常数,多开了三个数组分别记录每一个数属于哪个块,以及每一个块的左右端点是多少。

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define rg register
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = 4e4 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch)) {ans = ans * + ch - ''; ch = getchar();}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) x = -x, putchar('-');
if(x >= ) write(x / );
putchar(x % + '');
} int n, m, a[maxn], t[maxn]; int S, Cnt = , blo[maxn], lb[], rb[];
int sum[][maxn], ans[][], num[maxn];
void init()
{
S = sqrt(n);
Cnt = (n % S) ? n / S : n / S + ;
for(int i = ; i <= Cnt; ++i) lb[i] = (i - ) * S, rb[i] = i * S - ;
rb[Cnt] = n; //一定要有,否则会gg
for(int i = , j = ; i <= n; ++i) blo[i] = j, j += (i == rb[j]);
for(int i = ; i <= Cnt; ++i)
{
for(int j = ; j <= n; ++j) sum[i][j] += sum[i - ][j];
for(int j = lb[i]; j <= rb[i]; ++j) sum[i][a[j]]++;
}
for(int i = ; i <= Cnt; ++i)
{
Mem(num, ); int Max = -, pos;
for(int j = lb[i], k = i; j <= n; ++j)
{
if(++num[a[j]] > Max) Max = num[a[j]], pos = a[j];
if(num[a[j]] == Max && a[j] < pos) pos = a[j];
if(j == rb[k]) ans[i][k] = pos, k++;
}
}
}
int temp[], cp = ;
int query(int L, int R)
{
Mem(num, ); cp = ;
int l = blo[L], r = blo[R];
int Max = -, pos;
if(l == r)
{
for(int i = L; i <= R; ++i)
{
if(++num[a[i]] > Max) Max = num[a[i]], pos = a[i];
if(num[a[i]] == Max && a[i] < pos) pos = a[i];
}
return pos;
}
pos = ans[l + ][r - ]; Max = sum[r - ][pos] - sum[l][pos];
for(int i = L; i <= rb[l]; ++i)
{
if(!num[a[i]]) temp[++cp] = a[i];
num[a[i]]++;
}
for(int i = lb[r]; i <= R; ++i)
{
if(!num[a[i]]) temp[++cp] = a[i];
num[a[i]]++;
}
for(int i = ; i <= cp; ++i)
{
int tp = sum[r - ][temp[i]] - sum[l][temp[i]] + num[temp[i]];
if(tp > Max) Max = tp, pos = temp[i];
if(tp == Max && temp[i] < pos) pos = temp[i];
}
return pos;
} int Ans = ; int main()
{
n = read(); m = read();
for(int i = ; i <= n; ++i) t[i] = a[i] = read();
sort(t + , t + n + );
int _n = unique(t + , t + n + ) - t - ;
for(int i = ; i <= n; ++i)
a[i] = lower_bound(t + , t + _n + , a[i]) - t;
init();
for(int i = ; i <= m; ++i)
{
int L = read(), R = read();
L = (L + Ans - ) % n + ; R = (R + Ans - ) % n + ;
if(L > R) swap(L, R);
Ans = t[query(L, R)]; //别忘了输出原数
write(Ans), enter;
}
return ;
}

luogu P4168 [Violet]蒲公英的更多相关文章

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

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

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

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

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

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

  4. 洛谷 P4168 [Violet] 蒲公英

    历尽千辛万苦终于AC了这道题目... 我们考虑1个区间\([l,r]\), 被其完整包含的块的区间为\([L,R]\) 那么众数的来源? 1.\([l,L)\)或\((R,r]\)中出现的数字 2.\ ...

  5. P4168 [Violet]蒲公英

    神仙分块题?其实还是很简单的,res[i][j]表示第i块到第j块的众数,然后再用sum[i][j]表示前i块中j这个种类出现的次数,然后分块瞎搞就行了,感觉我写的十分简洁,好评( //author ...

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

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

  7. [洛谷P4168][Violet]蒲公英

    题目大意:有$n(n\leqslant4\times10^4)$个数,$m(m\leqslant5\times10^4)$个询问,每次问区间$[l,r]$内的众数,若相同输出最小的,强制在线. 题解: ...

  8. Luogu P1445[Violet]樱花/P4167 [Violet]樱花

    Luogu P1445[Violet]樱花/P4167 [Violet]樱花 真·双倍经验 化简原式: $$\frac{1}{x}+\frac{1}{y}=\frac{1}{n!}$$ $$\frac ...

  9. luogu P4168 蒲公英+ 分块学习笔记

    传送门 题目描述 在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关. 为了简化起见,我们把所有的蒲公英看成一个长度为n的序列\((a_1,a_2..a_n)\),其中 \(a_i\)为一 ...

随机推荐

  1. Android IntentFilter 匹配原则浅析

    1 Intent分为两大类,显式和隐式. 显式事件,就是指通过 component Name 属性,明确指定了目标组件的事件. 比如我们新建一个Intent,指名道姓的说,此事件用于启动名为" ...

  2. 新手 php连接数据库大概。简单过程浅析以及遇到的问题分析

    原文作者:aircraft 原文地址: https://www.cnblogs.com/DOMLX/p/8116845.html 重点:PHP运行在服务器上的请记住!!! 1.在连接数据库与PHP之前 ...

  3. Oracle关于All和Any

    简单的说 All等价于N个And语句,Any等价于N个or语句.

  4. java里面的package/import 和PHP里面的namespace/use 是一模一样的吗

    java里面的package/import 和PHP里面的namespace/use 是一模一样的吗? java: php package mypage; namespace mypage; impo ...

  5. UML建模概述

    UML的组成主要有事物.图.关系. UML中的事物: (1)构件事物:UML模型的静态部分,描述概念或物理元素,包括以下 a. 类:类是对一组具有相同属性.相同操作.相同关系和相同语义的对象的抽象.包 ...

  6. 跨页面传值2之cookie多值使用

    单值cookie结构 CookieKeyName——CookieValue CookieKeyName2——CookieValue2 ............... 通过CookieKeyName进行 ...

  7. jquery解析xml

    更多的项目都是在解析json,今天临时让解析几个xml文件,其实都一样,总结一下吧. 例如我们有这样一个xml文件 <?xml version="1.0" encoding= ...

  8. Backbone事件机制核心源码(仅包含Events、Model模块)

    一.应用场景 为了改善酷版139邮箱的代码结构,引入backbone的事件机制,按照MVC的分层思想搭建酷版云邮局的代码框架.力求在保持酷版轻量级的基础上提高代码的可维护性.   二.遗留问题 1.b ...

  9. css随堂笔记(三)

    Css随堂笔记(三) 1 关于背景图片   A 设置背景图片:background-image:url(“图片的路径”):   B 背景图片位置: background-position:1 方位名词 ...

  10. linux 中环境变量配置文件说明

    1. 修改/etc/profile文件 特点:所有用户的shell都有权使用你配置好的环境变量 说明:如果你的电脑仅用作开发,建议使用此配置,因为所有用户的shell都有权使用你配置好的环境变量,所以 ...