【AcWing 249. 蒲公英】

题意:

长度为n的序列,给定区间,求区间众数,如果出现次数相同,输出编号最小的

题解:

区间众数,不带修改,强制在线(否则可以莫队)
没有什么好办法那就只能暴力分块
分块,预处理任意两个大块之间的众数,相当于求出所有后缀的众数情况(枚举左块的端点,n*sqrt(n))
询问[l,r]中众数肯定是大块idl+1 ~ idr-1的众数,或者小块中的某个数
这一共是有sqrt(n)个候选答案,需要统计其在区间[l,r]内的出现次数,
第一个方法是用adj[x]记录x的所有出现次数,那么x在[l,r]内的出现次数就是:

upper_bound(adj[x].begin(), adj[x].end(), r) - lower_bound(adj[x].begin(), adj[x].end(), l)

这个做法的复杂度是O(nsqrt(n)logn)
第二个方法是预处理每个数在所有块中出现次数的前缀(n*sqrt(n)),这样直接就可以用差分来求次数,可以省掉第一个方法中的查找(去掉log),复杂度O(nsqrt(n))

代码:

代码有详细注释
貌似方法一会超时,只有方法二可以过

方法一:

#pragma optimize("Ofast")
#include<bits/stdc++.h>
#define MAXN 40005
#define MAXB 2005
using namespace std;
typedef long long ll;int N,M,B;
int a[MAXN], c[MAXN];
int d[MAXB][MAXB];vector<int> adj[MAXN];void init(){int cnt[MAXN], res;for(int l=0;l<=N;l+=B)//枚举左块 {if(l==0) continue;memset(cnt, 0, sizeof(cnt));res = 0;for(int r=l;r<=N;r++)//枚举右边界 {++cnt[a[r]];bool f1=cnt[a[r]] > cnt[res];//出现次数最多 bool f2=( cnt[a[r]] == cnt[res] && a[r] < res);//出现次数一样,编号更小 if(f1||f2) res = a[r];if((r+1)%B==0 || r==N) d[l/B][r/B] = res;//第l/B块到第r/B块的众数是res }}
}inline int num(const int& l, const int& r, const int& x){//在[l,r]范围内x出现几次 return upper_bound(adj[x].begin(), adj[x].end(), r) - lower_bound(adj[x].begin(), adj[x].end(), l);
}int query(int l, int r){int ans = 0;int idl = l/B, idr = r/B;if(idl-1 < idr) //如果idl在idr的左侧(或者一样) ans = d[idl+1][idr-1];int n = num(l,r,ans), n1;//n和n1表示出现数量//ans为出现次数最多的数的编号 //-----以下为分块的常规操作 if(idl==idr){for(int i=l;i<=r;i++){n1 = num(l,r,a[i]);//查看块内是否有数字大于n if(n < n1 || n == n1 && a[i] < ans) ans = a[i], n = n1;}}else{for(int i=l;i<(idl+1)*B;i++){n1 = num(l,r,a[i]);if(n < n1 || n == n1 && a[i] < ans) ans = a[i], n = n1;}for(int i=idr*B;i<=r;i++){n1 = num(l,r,a[i]);if(n < n1 || n == n1 && a[i] < ans) ans = a[i], n = n1;}}return c[ans];
}int main(){scanf("%d%d", &N, &M);B = sqrt(N); for(int i=1;i<=N;i++){scanf("%d", &a[i]);}memcpy(c,a,sizeof(a));sort(c+1, c+1+N);for(int i=1;i<=N;i++){a[i] = lower_bound(c+1, c+1+N, a[i]) - c;adj[a[i]].push_back(i);//a[i]在哪些位置出现过 }//init();int last = 0, l, r;while(M--){scanf("%d%d", &l, &r);l = (l+last-1)%N + 1;r = (r+last-1)%N + 1;if(l > r) swap(l, r);//cout<<"l r "<<l<<" "<<r<<endl;last = query(l,r);printf("%d\n", last);}return 0;
}

方法二:

#pragma optimize("Ofast")
#include<bits/stdc++.h>
#define MAXN 40005
#define MAXB 2005
using namespace std;
typedef long long ll;int N,M,B;
int a[MAXN], c[MAXN];
int s[MAXB][MAXN], d[MAXB][MAXB];inline int num(int idl, int idr, int x){//利用差分求出现次数 if(idl>idr) return 0;if(idl==0) return s[idr][x];else return s[idr][x] - s[idl-1][x];
}
int cnt[MAXN];
void init(){for(int i=0;i<N;i++){if(i>0 && i%B==0){//到了下一块 for(int j=0;j<N;j++){s[i/B][j] = s[i/B-1][j];//赋值前一块的情况 }}++s[i/B][a[i]];}// 上述内容为预处理每个数在所有块中出现次数的前缀 //下方内容为求出任意2个大块之间的众数int res;for(int l=0;l<N;l+=B){memset(cnt, 0, sizeof(cnt));res = 0;for(int r=l;r<N;r++){++cnt[a[r]];if(cnt[a[r]] > cnt[res] || cnt[a[r]] == cnt[res] && a[r] < res) res = a[r];if((r+1)%B==0 || (r+1)==N) d[l/B][r/B] = res;}}
}int query(int l, int r){int ans = 0;int idl = l/B + 1, idr = r/B - 1;if(idl <= idr) ans = d[idl][idr];int n = num(idl,idr,ans), n1;if(l/B == r/B){for(int i=l;i<=r;i++) ++cnt[a[i]];for(int i=l;i<=r;i++){if(cnt[a[i]]==0) continue;n1 = num(idl, idr, a[i]) + cnt[a[i]];if(n < n1 || n == n1 && a[i] < ans) ans = a[i], n = n1;cnt[a[i]] = 0;}}else{for(int i=l;i<idl*B;i++) ++cnt[a[i]];for(int i=(idr+1)*B;i<=r;i++) ++cnt[a[i]];for(int i=l;i<idl*B;i++){if(cnt[a[i]]==0) continue;n1 = num(idl, idr, a[i]) + cnt[a[i]];if(n < n1 || n == n1 && a[i] < ans) ans = a[i], n = n1;cnt[a[i]] = 0;}for(int i=(idr+1)*B;i<=r;i++){if(cnt[a[i]]==0) continue;n1 = num(idl, idr, a[i]) + cnt[a[i]];if(n < n1 || n == n1 && a[i] < ans) ans = a[i], n = n1;cnt[a[i]] = 0;}}return c[ans];
}int main(){//ios::sync_with_stdio(0);scanf("%d%d", &N, &M);B = sqrt(N); for(int i=0;i<N;i++){scanf("%d", &a[i]);}memcpy(c,a,sizeof(a));sort(c, c+N);for(int i=0;i<N;i++){a[i] = lower_bound(c, c+N, a[i]) - c;}//init();memset(cnt, 0, sizeof(cnt));int last = 0, l, r;while(M--){scanf("%d%d", &l, &r);l = (l+last-1)%N + 1;r = (r+last-1)%N + 1;if(l > r) swap(l, r);--l; --r;//cout<<"l r "<<l<<" "<<r<<endl;last = query(l,r);printf("%d\n", last);}return 0;
}

【AcWing 249. 蒲公英】相关推荐

  1. 【ACWing】247. 亚特兰蒂斯

    题目地址: https://www.acwing.com/problem/content/249/ 有几个古希腊书籍中包含了对传说中的亚特兰蒂斯岛的描述.其中一些甚至包括岛屿部分地图.但不幸的是,这些 ...

  2. 【ACWing】1020. 潜水员

    题目地址: https://www.acwing.com/problem/content/1022/ 潜水员为了潜水要使用特殊的装备.他有一个带 2 2 2种气体的气缸:一个为氧气,一个为氮气.让潜水 ...

  3. AcWing算法提高课笔记

    目录 Level2 1.动态规划--从集合角度考虑DP问题 1.1 数字三角形模型 1.1.1摘花生 1.1.2最低通行费 1.1.3方格取数 1.1.4传纸条 1.2 最长上升子序列模型 1.2.1 ...

  4. 用CSS在博客园底部加上蒲公英动态效果的实现方法

    在做网站的时候我们经常想要实现一些动态效果来为网站增添一点活力, 而通常情况下,实现动态效果都需要用到JS代码.JS能够实现比较复杂且炫酷的动态效果, 但通常情况下JS会拖慢网站的响应速度且不利于搜索 ...

  5. 新闻更新php html,phphtml 新闻发布系统,运用php+mysql,里面包括数据库和php文件。 Other systems 其他 249万源代码下载- www.pudn.com...

    文件名称: phphtml下载  收藏√  [ 5  4  3  2  1 ] 开发工具: PHP 文件大小: 1076 KB 上传时间: 2016-01-07 下载次数: 0 提 供 者: zfl ...

  6. AcWing 734. 能量石 (01背包)+(贪心 - 领项交换)

    AcWing 734. 能量石 #include<cstdio> #include<algorithm> #include<cstring> #include< ...

  7. 解题报告:AcWing 352. 闇の連鎖(树上差分、方案统计)

    https://www.acwing.com/problem/content/354/ 在没有附加边的情况下,我们发现这是一颗树,那么再添加条附加边(x,y)后,会造成(x,y)之间产生一个环 如果我 ...

  8. 极视教育的课程怎么样_蒲公英教育加盟怎么样?

    蒲公英教育一直以来为大家带来的都是适合的课程.以孩子为中心,激发孩子学习兴趣,提升思维能力,让孩子通过蒲公英教育的课程,爱上学习,爱上思考.蒲公英教育更为全国各地孩子打造更优质的在线思维训练课程.那么 ...

  9. 解决Windows平台通过cURL上传APP到蒲公英pgyer平台时无法使用中文升级描述的问题...

    解决Windows平台通过cURL上传APP到蒲公英pgyer平台时无法使用中文升级描述的问题 官方上传命令 curl -F file=@"315.apk" -F uKey=XXX ...

最新文章

  1. 基于半监督学习的单体型组装算法
  2. 漫谈时序设计(3)走进时序约束的大门!
  3. 小米Redmi 5G旗舰 K30 Pro,最大亮点:怼华为荣耀
  4. Symbian c++ MCameraObserver类的方法解释
  5. linux中probe函数传递参数的寻找(下)
  6. 爬虫基础, 乱码问题, jupyter, urllib, requests, lxml, multiprocessing并发, session, beautifulsoup...
  7. 笔记本移交_创建完美的设计移交
  8. 『原创』.Net CF下ListView的数据绑定
  9. 20180320作业2:进行代码复审训练
  10. 【Python】彩色图片转为灰度图(4行脚本搞定)
  11. 博弈论(二)完全信息静态博弈
  12. 海军领域搜狗细胞词库
  13. 医学CT图像三维重建代码
  14. 麦客CEO李卉:实践证明肯钻营的“小而美”亦动人|企服三会系列报道
  15. qq安装路径无效Linux,QQ提示安装路径无效您没有权限的两种解决办法
  16. MU计算机里代表什么,计算器上M+、M-、MU、GT等分别代表意思-mu代表啥
  17. java编程找出吸血鬼数字,找出四位數的所有吸血鬼數字(JAVA)
  18. 【华为OD机试真题 C++】数字涂色 【2022 Q4 | 100分】
  19. 阮一峰 / ES6 数组的解构赋值
  20. 物联网平台分为几层,你了解吗

热门文章

  1. 全球科技界最鼓舞人心领袖揭晓!马斯克第一,马云第五
  2. 快速成长为数据挖掘高手的秘诀
  3. 计算机试题dddd,数据库系统概论试题及答案dddd_Image_Marked.pdf
  4. android sdk中添加自定义api,android SDK中添加自定义api【转】
  5. mysql数据库已连接数据库_001. 【已解决】Java连接MYSQL 数据库的连接步骤
  6. 二维数组各行分别求和_【PyTorch入门】之十分钟看懂二维卷积层的运算、实现及应用...
  7. js 浅拷贝直接赋值_浅析JavaScript解析赋值、浅拷贝和深拷贝的区别
  8. 俄语使用计算机怎么说,计算机俄语常用词汇
  9. kotlin中mainactivity无法直接调用xml中的控件_使用52North 客户端接口调用OGC WPS服务...
  10. linux开发板显示横向彩虹,给 Linux 终端的输出添加彩虹特效的命令