BZOJ2724 蒲公英


题目背景

亲爱的哥哥:

你在那个城市里面过得好吗?

我在家里面最近很开心呢。昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了。我觉得把那么可怕的怪物召唤出来的那个坏蛋也很坏呢。不过奶奶说他是很难受的时候才做出这样的事的……

最近村子里长出了一大片一大片的蒲公英。一刮风,这些蒲公英就能飘到好远的地方了呢。我觉得要是它们能飘到那个城市里面,让哥哥看看就好了呢!

哥哥你要快点回来哦!

爱你的妹妹 Violet

Azure 读完这封信之后微笑了一下。

“蒲公英吗……”

题目描述

在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。

为了简化起见,我们把所有的蒲公英看成一个长度为n的序列 (a1,a2..an)" role="presentation">(a1,a2..an)(a1,a2..an)其中 ai" role="presentation">aiai为一个正整数,表示第i棵蒲公英的种类编号。

而每次询问一个区间 [l,r],你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。

注意,你的算法必须是在线的

输入输出格式

输入格式:

第一行两个整数 n,m ,表示有n株蒲公英,m 次询问。

接下来一行n个空格分隔的整数 ai" role="presentation">aiai ,表示蒲公英的种类

再接下来m 行每行两个整数 l0,r0" role="presentation">l0,r0l0,r0 ,我们令上次询问的结果为 x(如果这是第一次询问, 则 x=0)。

令l=(l0+x−1)modn+1,r=(r0+x−1)modn+1" role="presentation">l=(l0+x−1)modn+1,r=(r0+x−1)modn+1l=(l0+x−1)modn+1,r=(r0+x−1)modn+1 ,如果 l>r,则交换 l,r 。

最终的询问区间为[l,r]。

输出格式:

输出m 行。每行一个整数,表示每次询问的结果。

输入输出样例

输入样例#1

6 3

1 2 3 2 1 2

1 5

3 6

1 5

输出样例#1:

1

2

1

说明

对于 20% 的数据,保证 1≤n,m≤30001≤n,m≤3000" role="presentation">1≤n,m≤30001≤n,m≤30001≤n,m≤30001≤n,m≤3000。

对于 100% 的数据,保证 1≤n≤40000,1≤m≤50000,1≤ai≤109" role="presentation">1≤n≤40000,1≤m≤50000,1≤ai≤1091≤n≤40000,1≤m≤50000,1≤ai≤109


区间求众数

分块

cnt[i][j]" role="presentation">cnt[i][j]cnt[i][j]表示第i个数在前j个块中的数量

ans[i][j]" role="presentation">ans[i][j]ans[i][j]表示第i到第j个块中的众数

先离散,然后预处理cnt" role="presentation">cntcnt和ans" role="presentation">ansans,对于查询,先把答案设定为完整块的众数,不是完整块的部分就暴力枚举进行比较好了

时间&空间效率O(nsqrt(n))" role="presentation">O(nsqrt(n))O(nsqrt(n))


#include<bits/stdc++.h>
using namespace std;
#define N 210
#define M 40010
#define For(x,a,b) for(int x=a;x<=b;x++)
map<int,int> mp;
int n,m,tot=0,lastans=0;
int a[M],b[M],pre[M],t[N]={0};
int block[M],L[N],R[N];
int cnt[M][N]={0},ans[N][N]={0};
int calc(int id,int lb,int rb){
return cnt[id][rb]-cnt[id][lb-1];
}
void init(){
int siz=sqrt(n);
For(i,1,n)block[i]=(i-1)/siz+1;
int bsiz=block[n];
For(i,1,bsiz)L[i]=R[i-1]+1,R[i]=min(n,i*siz);
For(i,1,n)cnt[b[i]][block[i]]++;
For(i,1,tot)For(j,1,bsiz)cnt[i][j]+=cnt[i][j-1];
For(i,1,bsiz)
For(j,i,bsiz){
int tmp=ans[i][j-1];
For(k,L[j],R[j]){
int t1=calc(b[k],i,j),t2=calc(tmp,i,j);
if((t1==t2&&pre[b[k]]<pre[tmp])||t1>t2)tmp=b[k];
}
ans[i][j]=tmp;
}
}
bool check(int id,int tmp){
if(t[id]>t[tmp])return 1;
if(t[id]==t[tmp]&&pre[id]<pre[tmp])return 1;
return 0;
}
int solve(int l,int r){
int pl=block[n]+1,pr=0;
For(i,1,block[n])if(L[i]>=l)pl=min(pl,i);
For(i,1,block[n])if(R[i]<=r)pr=max(pr,i);
if(pl>pr){
int tmp=0;
For(i,l,r)t[b[i]]=0;
For(i,l,r)t[b[i]]++;
For(i,l,r)if(check(b[i],tmp))tmp=b[i];
return tmp;
}
int tmp=ans[pl][pr];
t[tmp]=calc(tmp,pl,pr);
For(i,l,L[pl]-1)t[b[i]]=calc(b[i],pl,pr);
For(i,R[pr]+1,r)t[b[i]]=calc(b[i],pl,pr);
For(i,l,L[pl]-1)t[b[i]]++;
For(i,R[pr]+1,r)t[b[i]]++;
For(i,l,L[pl]-1)if(check(b[i],tmp))tmp=b[i];
For(i,R[pr]+1,r)if(check(b[i],tmp))tmp=b[i];
return tmp;
}
int main(){
scanf("%d%d",&n,&m);
For(i,1,n){
scanf("%d",&a[i]);
if(!mp.count(a[i])){
mp[a[i]]=++tot;
pre[tot]=a[i];
}
b[i]=mp[a[i]];
}
init();
For(i,1,m){
int l,r;scanf("%d%d",&l,&r);
l=(l+lastans-1)%n+1;
r=(r+lastans-1)%n+1;
if(l>r)swap(l,r);
lastans=pre[solve(l,r)];
printf("%d\n",lastans);
}
return 0;
}

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

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

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

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

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

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

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

  4. 【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 ...

  5. BZOJ2724 [Violet]蒲公英 分块

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

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

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

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

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

  8. [Violet]蒲公英 分块

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

  9. [BZOJ2724] 蒲公英

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

随机推荐

  1. POJ 2186 Popular Cows(强连通分量Kosaraju)

    http://poj.org/problem?id=2186 题意: 一个有向图,求出点的个数(任意点可达). 思路: Kosaraju算法的第一次dfs是后序遍历,而第二次遍历时遍历它的反向图,从标 ...

  2. Vuex最基本样例

    通过vue-cli建立基本脚手架(需要安装vuex),需要新建一个store.js文件.基本目录如下 1,store.js文件代码: import Vue from 'vue' import Vuex ...

  3. CountDownLatch详解

    功能描述 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 常见用法 多个人等一个信号后继续执行操作.例如5个运动员,等一个发令员的枪响. 一个人等多个人的信号. ...

  4. angularjs1 自定义图片查看器(可旋转、放大、缩小、拖拽)

    笔记: angularjs1 制作自定义图片查看器(可旋转.放大.缩小.拖拽) 2018-01-12 更新  可以在我的博客  查看我 已经封装好的 纯 js写的图片查看器插件    博客链接 懒得把 ...

  5. Flutter新手第一个坑:Could not find com.android.tools.lint:lint-gradle:26.1.1.

    解决方法1:修改build.gradle,注释掉jcenter(),google().使用阿里的镜像.原因是jcenter google库无法访问到导致的问题.虽然我有万能的爬墙工具,开启全局代理依然 ...

  6. led,key通用IO的端口

    1 注意通用IO端口, GPBCON 只能控制一个GPBDAT位(对应的位),而GPBUP可以使能GPBCON.

  7. Windows 10上强制Visual Studio 2017 以管理员身份运行

    1. 打开VS的安装目录,找到devenv.exe,右键,选择“兼容性疑难解答”. 2. 选择“疑难解答程序” 3. 选择“该程序需要附加权限” 4. 确认用户帐户控制后,点击测试程序,不然这个对话框 ...

  8. 开启Tomcat APR运行模式,优化并发性能

    Tomcat支持三种接收请求的处理方式:BIO.NIO.APR 1>.BIO模式:阻塞式I/O操作,表示Tomcat使用的是传统JavaI/O操作(即Java.io包及其子包).Tomcat7以 ...

  9. 在接口请求时报错Unrecognized field &quot;zZF1&quot

    这个问题是json序列化问题,当参数中出现大写字母组成的字段时(例如:ZZF1),此时需在字段上加入注解:@JsonProperty(value = "ZZF1")

  10. 上下行分流下行负载方式和能ping通但不能打开

    1 下行线路负载方式选择  目的端口+协议  否则有可能出现微信443端口图片打不开的情况. 2.彭ping通但是打不开的情况下将上行线路mtu值改小 由1500改为1450