[HDU 5875] Function (单调栈/(RMQ+二分))
来源:互联网 发布:淘宝客服售前问题用语 编辑:程序博客网 时间:2024/06/11 16:59
链接
HDU 5875
题意
2016大连站网赛的1008。
给出一个长度为N的序列,和Q组询问,对每组询问[l, r],输出a[l] % a[l+1] % … % a[r],l等于r的时候输出a[l]即可。
题解
这题网上貌似有各种解法花式AC,这里给出两种。
第一种是预处理+暴力,对序列a,对a[i]求出其右侧第一个小于等于a[i]的值的下标,因为大于某个余数的值是没有意义的,在查询的时候可以加速计算,跳过一些不必要的值的取模。
但是这种方法的上界是O(n^2)的,比如一个很长的下降序列就可以轻松T掉这种做法,但是在这题里可以<1s AC,效率还是很高的(其实有点坑,早知道这么能过我们也这么写了)。
第二种做法是RMQ+二分,st表维护序列a的最小值,在处理某个查询的时候二分区间,可以查到区间小于等于某值的第一个值(最左侧)的下标,取模后继续查询直到区间右端点即可。
这种做法的复杂度是n*logn*logn的,每次二分区间寻找下一个小于等于该值的值需要logn,一个数在取模的过程中至少降低一半,这个衰减比logn还快,加上区间不停缩短,所以O(n*logn*logn)绝对是充裕的。
值的一提的是我这么做竟然T了,原因是我二分区间的函数是以递归形式写的,我改成迭代形式以后就过了,可见优化常数的重要性啊。。。
代码
单调栈预处理+暴力:
#include <cstdio>#include <iostream>using namespace std;#define next Next#define maxn (100010)int a[maxn], next[maxn];struct _node{ int idx, value;} _stack[maxn];int main(){ int T; cin >> T; while(T--) { int N; cin >> N; for(int i = 1, pre = -1; i <= N; i++) { scanf("%d", &a[i]); next[i] = 0; } for(int i = 1, top = 0; i <= N; i++) { while(top && _stack[top-1].value >= a[i]) { next[_stack[top-1].idx] = i; top--; } _stack[top].idx = i; _stack[top++].value = a[i]; } int M; cin >> M; for(int i = 0, l, r; i < M; i++) { scanf("%d%d", &l, &r); if(l == r) printf("%d\n", a[l]); else { int now = l, o = a[l]; while(now < r) { now = next[now]; if(!now || now > r) break; o %= a[now]; if(!o) break; } printf("%d\n", o); } } } return 0;}
RMQ(st表)+二分:
#include <cstdio>#include <cmath>#include <algorithm>#include <iostream>using namespace std;#define log2 Log2#define maxn (100010)int log2[maxn], st[maxn][32];void st_prepare(int n, int *arr){ log2[1] = 0; for(int i = 2; i <= n; i++) { log2[i] = log2[i-1]; if(i == (1 << log2[i] + 1)) log2[i]++; } for(int i = n-1; i >= 0; i--) { st[i][0] = arr[i]; for(int j = 1; i + (1 << j) - 1 < n; j++) { st[i][j] = min(st[i][j-1], st[i + (1 << j - 1)][j-1]); } }}inline int st_query(int l, int r){ int k = log2[r - l + 1]; return min(st[l][k], st[r - (1 << k) + 1][k]);}int st_find(int l, int r, int a){ int m; while(l <= r) { if(l == r) return st[l][0] <= a ? l : 0; m = (l + r) >> 1; if(st_query(l, m) <= a) r = m; else if(st_query(m+1, r) <= a) l = m+1; else return 0; } return 0;/* if(l == r) return st[l][0] <= a ? l : 0; int m = (l + r) >> 1, ret = 0; if(ret = st_find(l, m, a)) return ret; return st_find(m + 1, r, a);*/}int a[maxn];int main(){ int T; cin >> T; while(T--) { int N; cin >> N; for(int i = 1; i <= N; i++) scanf("%d", &a[i]); st_prepare(N + 1, a); int M, l, r, p, q, m, o; cin >> M; while(M--) { scanf("%d%d", &l, &r); if(l == r) { printf("%d\n", a[l]); continue; } p = l + 1, q = r, o = a[l]; while(p <= q) { m = st_find(p, q, o); if(!m) break; o %= a[m]; if(!o) break; p = m + 1; } printf("%d\n", o); } } return 0;}
0 0
- [HDU 5875] Function (单调栈/(RMQ+二分))
- hdu 5875 Function(二分RMQ)
- hdu 5875 Function 二分+rmq
- HDU 5875 Function (RMQ+二分)
- HDU 5089 Assignment(rmq+二分 或 单调队列)
- HDU5875-Function(RMQ + 二分)
- HDU 5875 Function(单调栈+在线倍增法)
- 两种解法-树形dp+二分+单调队列(或RMQ)-hdu-4123-Bob’s Race
- Hdu-5289 Assignment (二分+RMQ || 单调队列)
- [HDU 5696] 区间的价值 (单调栈+RMQ)
- HDU 5875 Function(logn取模+二分rmq)
- hdu 5875 Function (st+二分)
- Educational Codeforces Round 23 D. Imbalanced Array(单调栈或RMQ+二分)
- hdu 5875 Function 单调栈 + 暴力
- HDU 5875 Function (单调栈+暴力)
- HDU-5662 YJQQQAQ and the function (枚举&&单调栈)
- HDU 5289 Assignment (RMQ+二分)
- HDU 5289 Assignment (二分+RMQ)
- 【翻译】安卓新播放器EXOplayer介绍
- Pcomm.dll(串口通讯库)中流控函数操作的说明手册
- 递归构造格雷码
- SAP AUTHORITY-CHECK 的使用
- Cordova 环境搭建及使用
- [HDU 5875] Function (单调栈/(RMQ+二分))
- Dij+堆优化
- iOS开发之第三方分享QQ分享实现
- 以戒为师
- SAP MB51物料凭证清单程序增强增加四个字段
- 在数据库中添加自增字段值。该字段是非主键。
- 32. Longest Valid Parentheses
- stl源码剖析之vector,list,deque迭代器分析
- 关于选择排序