Violet蒲公英
题目要求求出给定区间内编号最小的众数,强制在线。
虽然说这是个黑题……不过我们可以用暴力分块解决它。首先先对所有数离散化,这个不影响众数。我们先预处理出每个数在前i个块内出现了多少次,再预处理出块i到块j内最小众数是谁。前者很好预处理,后者的话,我们只要固定i,之后向后枚举,每次新加入一个数的时候就比较出现最多次的元素来更新当前众数。如果到了块末尾,就更新块的答案。
查询的时候,整块的我们直接去计算过的答案,之后对于每一个出现在零散位置的元素,我们记录下来,之后计算他们在整块中出现了多少次(前缀和相减即可),这样比较出出现次数最多的元素就可以。
这题的处理稍微有点复杂,我的做法是开个栈来记录当前出现在零散位置的元素。
看一下代码。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n') using namespace std;
typedef long long ll;
const int M = ;
const int N = ;
const int INF = ; int read()
{
int ans = ,op = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') op = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
ans *= ;
ans += ch - '';
ch = getchar();
}
return ans * op;
} int n,m,B,a[M],l[N],r[N],sum[M][N],ans[N][N],x,y,last,b[M],cnt,blo[M],tot,g = ,cur[M],maxx;
int sta[M],top,mpos; void init()
{
rep(i,,cnt)
{
rep(j,,n) sum[j][i] += sum[j][i-];
rep(j,l[i],r[i]) sum[a[j]][i]++;
}
rep(i,,cnt)
{
memset(cur,,sizeof(cur)),maxx = mpos = ,g = i;
rep(j,l[i],n)
{
cur[a[j]]++;
if(cur[a[j]] > maxx) maxx = cur[a[j]],mpos = a[j];
else if(cur[a[j]] == maxx && a[j] < mpos) mpos = a[j];
if(j == r[g]) ans[i][g] = mpos,g++;
}
}
} int query(int x,int y)
{
memset(cur,,sizeof(cur)),maxx = mpos = ;
int L = blo[x],R = blo[y];
if(L == R)
{
rep(i,x,y)
{
cur[a[i]]++;
if(cur[a[i]] > maxx) maxx = cur[a[i]],mpos = a[i];
else if(cur[a[i]] == maxx && a[i] < mpos) mpos = a[i];
}
return mpos;
}
int p = ans[L+][R-],now = sum[p][R-] - sum[p][L];
rep(i,x,r[L])
{
if(!cur[a[i]]) sta[++top] = a[i];
cur[a[i]]++;
}
rep(i,l[R],y)
{
if(!cur[a[i]]) sta[++top] = a[i];
cur[a[i]]++;
}
mpos = p;
while(top)
{
int k = sta[top],q = sum[k][R-] - sum[k][L] + cur[k];
if(q > now) now = q,mpos = k;
else if(q == now && k < mpos) mpos = k;
top--;
}
return mpos;
} int main()
{
n = read(),m = read(),B = sqrt(n);
cnt = (n % B) ? n / B + : n / B;
rep(i,,cnt) l[i] = r[i-] + ,r[i] = l[i] + B - ;
r[cnt] = n;
rep(i,,n) a[i] = b[i] = read();
sort(b+,b++n),tot = unique(b+,b++n) - b - ;
rep(i,,n) a[i] = lower_bound(b+,b++tot,a[i]) - b;
//rep(i,1,n) printf("%d ",a[i]);enter;
rep(i,,n)
{
blo[i] = g;
if(i == r[g]) g++;
}
init();
rep(i,,m)
{
x = read(),y = read();
x = (x + last - ) % n + ,y = (y + last - ) % n + ;
if(x > y) swap(x,y);
last = b[query(x,y)];
printf("%d\n",last);
}
return ;
}
Violet蒲公英的更多相关文章
- 洛谷 P4168 [Violet]蒲公英 解题报告
P4168 [Violet]蒲公英 题目背景 亲爱的哥哥: 你在那个城市里面过得好吗? 我在家里面最近很开心呢.昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多 ...
- 【luogu1468】[Violet]蒲公英--求区间众数
题目背景 亲爱的哥哥: 你在那个城市里面过得好吗? 我在家里面最近很开心呢.昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了.我觉得把那么可怕 ...
- [Violet]蒲公英 分块
发现写算法专题老是写不动,,,, 所以就先把我在luogu上的题解搬过来吧! 题目大意:查询区间众数,无修改,强制在线 乍一看是一道恐怖的题,仔细一看发现并没有那么难: 大致思路是这样的,首先我们要充 ...
- P4168 [Violet]蒲公英 区间众数
$ \color{#0066ff}{ 题目描述 }$ 在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关. 为了简化起见,我们把所有的蒲公英看成一个长度为n的序列 \((a_1,a_2.. ...
- 洛谷 P4168 [Violet] 蒲公英
历尽千辛万苦终于AC了这道题目... 我们考虑1个区间\([l,r]\), 被其完整包含的块的区间为\([L,R]\) 那么众数的来源? 1.\([l,L)\)或\((R,r]\)中出现的数字 2.\ ...
- P4168 [Violet]蒲公英
神仙分块题?其实还是很简单的,res[i][j]表示第i块到第j块的众数,然后再用sum[i][j]表示前i块中j这个种类出现的次数,然后分块瞎搞就行了,感觉我写的十分简洁,好评( //author ...
- BZOJ2724 [Violet]蒲公英(分块)
区间众数.分块,预处理任意两块间所有数的众数,和每块中所有数的出现次数的前缀和.查询时对不是整块的部分暴力,显然只有这里出现的数可能更新答案.于是可以优美地做到O(n√n). #include< ...
- p4168 [Violet]蒲公英(分块)
区间众数的重题 和数列分块入门9双倍经验还是挺好的 然后开O2水过 好像有不带log的写法啊 之后在补就是咕咕咕 // luogu-judger-enable-o2 #include <cstd ...
- BZOJ2724 [Violet]蒲公英 分块
题目描述 经典区间众数题目 然而是权限题,所以题目链接放Luogu的 题解 因为太菜所以只会$O(n*\sqrt{n}+n*\sqrt{n}*log(n))$的做法 就是那种要用二分的,并不会clj那 ...
- [Violet]蒲公英
description 在线询问区间众数. data range \[n\le 40000,m\le 50000,a_i\le 10^9\] solution 自己分块不行于是\(\%\)了\(yyb ...
随机推荐
- zju 3209 dancing links 求取最小行数
题目可以将每一个格子都看做是一列,每一个矩形作为1行,将所有格子进行标号,在当前矩形中的格子对应行的标号为列,将这个点加入到十字链表中 最后用dlx求解精确覆盖即可,dance()过程中记得剪枝 #i ...
- 没有上司的舞会(hdu 1520)
题目描述 Description Ural大学有N个职员,编号为1~N.他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.每个职员有一个快乐指数.现在有个周年庆宴会 ...
- ie6 js报错汇总
假如ie6是一个非美女的人,那不知道为多少人乱刀砍多少次,假如不幸它是一个美女,那不知道要被多少人轮奸完之后还是乱刀砍死. ie6的js的错误说明总是很隐晦的,它喜欢和捉迷藏.报的行数和错误,常常不知 ...
- BZOJ4580: [Usaco2016 Open]248
n<=248个数字,可以进行这样的操作:将相邻两个相同的数字合并成这个数字+1,求最大能合成多少. f(i,j)--区间i到j能合成的最大值,f(i,j)=max(f(i,k)+1),f(i,k ...
- nginx学习网站收录
1.菜鸟教程 2. Nginx中文 3. Nginx官网 参考:http://www.cnblogs.com/knowledgesea/p/5175711.html
- 给Ubuntu更换成163的源(sources.list)Unable to locate package
Refer to http://www.crifan.com/ubuntu_change_sources_list_to_163/ 1. backup /etc/apt/sources.list 2. ...
- 前端学习之--html
html 文件就是充当模板使用,包含head头和body身体,body包含众多的标签,每个标签都使用尖括号包裹,内部由标签名和标签属性构成.其中标签分为2类: 1:块级标签,特点:占用一行,如:< ...
- LCA 求 树中两个点的距离
PS:在树中:dis(u,v)=dis(root,v)+dis(root,u)-2*dis(root,lca(u,v)); 这个性质可以写很多题. vector<int>mp[N];int ...
- mybatisplus代码生成器
一.随便建一个springboot工程,在pom文件中导入依赖 <!-- 模板引擎 --> <dependency> <groupId>org.apache.vel ...
- 获取鼠标位置的几个通用的JS函数
原文:http://www.open-open.com/code/view/1421401009218 /*两个通用函数,用于获取鼠标相对于整个页面的当前位置*/ function getX(e) { ...