【bzoj2724】[Violet 6]蒲公英
2015-11-18 20:39
381 查看
坑了好久的区间众数……
思路是分块。
设块的大小为ll,有xx个块
预处理第i个块和第j个块之间的众数和出现次数,这是O(xn)O(xn)的。
对于每个询问[l,r][l,r],如果l和r在同一个块里面,就暴力查询,这是O(l)O(l)的;如果不在同一个块,则先以预处理的信息得到中间连续的块的答案,然后再在最两边的两个块暴力查询每个数在中间出现的次数,然后更新答案。偷懒没多想,写了个主席树,所以是O(llogn)O(l\log n)的。
于是总的复杂度是O(xn+mllogn)O(xn + ml\log n)。
稍微计算+对拍,取l=100l=100左右的时候可以在时限内跑完。
思路是分块。
设块的大小为ll,有xx个块
预处理第i个块和第j个块之间的众数和出现次数,这是O(xn)O(xn)的。
对于每个询问[l,r][l,r],如果l和r在同一个块里面,就暴力查询,这是O(l)O(l)的;如果不在同一个块,则先以预处理的信息得到中间连续的块的答案,然后再在最两边的两个块暴力查询每个数在中间出现的次数,然后更新答案。偷懒没多想,写了个主席树,所以是O(llogn)O(l\log n)的。
于是总的复杂度是O(xn+mllogn)O(xn + ml\log n)。
稍微计算+对拍,取l=100l=100左右的时候可以在时限内跑完。
[code]#include <bits/stdc++.h> #define rep(i,a,b) for(int i=a,_=b;i<=_;i++) #define per(i,a,b) for(int i=a,_=b;i>=_;i--) #define maxn 50007 #define maxb (742) typedef int arr[maxn]; typedef int blk[maxb]; typedef int seg[maxn * 20]; inline int rd() { char c = getchar(); while (!isdigit(c)) c = getchar() ; int x = c - '0'; while (isdigit(c = getchar())) x = x * 10 + c - '0'; return x; } int BLOCKS; seg sz , lc , rc; arr belong , cnt , a , h , rt; blk st , ed , ans[maxb] , rec[maxb]; int n_tot , tot , n , m; void update(int pr , int&nr , int l , int r , int v) { if (!nr) nr = ++ n_tot; sz[nr] = sz[pr] + 1; if (l == r) return; int m = (l + r) >> 1; if (v <= m) rc[nr] = rc[pr] , update(lc[pr] , lc[nr] , l , m , v); else lc[nr] = lc[pr] , update(rc[pr] , rc[nr] , m + 1 , r , v); } int query(int pr , int nr , int l , int r , int v) { while (l < r) { int m = (l + r) >> 1; if (v <= m) nr = lc[nr] , pr = lc[pr] , r = m; else nr = rc[nr] , pr = rc[pr] , l = m + 1; } return sz[nr] - sz[pr]; } void input() { n = rd() , m = rd(); rep (i , 1 , n) h[i] = a[i] = rd(); } void discrete() { std::sort(h + 1 , h + n + 1); rep (i , 1 , n) a[i] = std::lower_bound(h + 1 , h + n + 1 , a[i]) - h; rep (i , 1 , n) update(rt[i - 1] , rt[i] , 1 , n , a[i]); } void init_block() { BLOCKS = 101; rep (i , 1 , n) belong[i] = (i - 1) / BLOCKS + 1; tot = belong ; rep (i , 1 , tot) st[i] = (i - 1) * BLOCKS + 1 , ed[i] = i * BLOCKS; rep (i , 1 , tot) { int mx = 0 , t = 0; rep (j , st[i] , n) { cnt[a[j]] ++; if (cnt[a[j]] > mx || (cnt[a[j]] == mx && a[j] < t)) mx = cnt[a[j]] , t = a[j]; ans[i][belong[j]] = t; rec[i][belong[j]] = cnt[t]; } rep (j , st[i] , n) cnt[a[j]] = 0; } } int get_ans(int l , int r) { int mx = 0 , t; if (belong[l] == belong[r]) { rep (i , l , r) cnt[a[i]] = 0; rep (i , l , r) cnt[a[i]] ++; rep (i , l , r) if (cnt[a[i]] > mx || (cnt[a[i]] == mx && a[i] < t)) mx = cnt[a[i]] , t = a[i]; } else { if (belong[l] - 1 < belong[r]) mx = rec[belong[l] + 1][belong[r] - 1] , t = ans[belong[l] + 1][belong[r] - 1]; rep (i , l , ed[belong[l]]) { int c = query(rt[l - 1] , rt[r] , 1 , n , a[i]); if (c > mx || (c == mx && a[i] < t)) t = a[i] , mx = c; } rep (i , st[belong[r]] , r) { int c = query(rt[l - 1] , rt[r] , 1 , n , a[i]); if (c > mx || (c == mx && a[i] < t)) t = a[i] , mx = c; } } return t; } void solve() { discrete(); init_block(); int ans = 0; #ifndef ONLINE_JUDGE freopen("data.out" , "w" , stdout); #endif rep (i , 1 , m) { int l = (rd() + ans - 1) % n + 1; int r = (rd() + ans - 1) % n + 1; if (l > r) std::swap(l , r); ans = h[get_ans(l , r)]; printf("%d\n" , ans); } } int main() { #ifndef ONLINE_JUDGE freopen("data.txt" , "r" , stdin); #endif input(); solve(); return 0; }
相关文章推荐
- Java学习笔记---继承和多态
- redis php扩展安装下载
- linux下mysql数据库常用命令以及中文乱码问题的解决
- js中startsWith 函数不能在任何浏览器兼容的问题
- 【Hadoop】HDFS的运行原理
- CANopen协议报文处理
- 【图文解释】快速排序算法
- 线性表的合并
- webrtc 学习资源 http://www.cnblogs.com/lingyunhu/p/3578218.html
- 加速优化android应用
- 漫谈机器学习经典算法—增强学习与马尔科夫决策过程
- 第十二周--项目4应用图的深度优先遍历思路求解问题 (5)
- Geometry-Shader Object
- android自定义弹出框样式实现
- XML 的组成语法及解析
- 简单工厂模式,抽象工厂模式,反射工厂模式的代码总结
- 【JavaScript】字符串--replace( )方法
- Kibana User Guide [4.2] » Getting Started with Kibana
- javaScript 注意点
- mysql编写存储过程hibernate4调用