RMQ+二分——GCD ( HDU 5726 ) ( 2016 Multi-University Training Contest 1 1004 )
来源:互联网 发布:国际软件学院 编辑:程序博客网 时间:2024/06/06 04:42
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5726分析:
给出一串数,然后进行区间查询,每次查询一个区间的gcd,并且要求同时输出和这个区间gcd值相等的其它区间的个数。题解:
1.RMQ快速区间查询:(此处查询的是GCD)
int dp[Maxn][21];//dp[i][j]表示从 number[i]开始,长度为2^j次的区间的最值void init(){ for (int i = 0; i < N; i++) //dp前的预处理,把数组读进去 dp[i][0] = numbers[i]; for (int j = 1; (1<<j) <= N; j++)//RMQ的初始化操作 { for (int i = 0; i+(1<<j)-1 < N; i++) { dp[i][j] = __gcd (dp[i][j-1], dp[i+(1<<(j-1))][j-1]); } }}int query(int l, int r) // 查询区间最值{ int k = 0; while ((1<<(k+1)) <= r-l+1) k++; return __gcd (dp[l][k], dp[r-(1<<k)+1][k]);}
2.二分处理相同GCD区间个数:
map <int, long long> gg; // first记录gcd值, second 记录相同gcd值下的区间个数void solve (){ for (int i = 0; i < N; i++) //枚举左端点 { int pos = N-1; while (pos >= i) //二分选定右端点 { int tmp = query(i, pos); int l = i, r = pos; while (r-l > 1) { int mid = (l+r)>>1; if (query(i, mid) == tmp) r = mid; else l = mid; } int cur; if (query(i, l) == tmp) cur = l; else cur = r; gg[tmp] += (pos-cur+1); // 表示区间[i, pos] 与 区间[i, cur+1]的GCD值相等,且等于tmp,所以gcd值等于tmp的数量由pos-cur+1 pos = cur-1; } }}
- 参考代码:
#include<iostream>#include<cstring>#include<cstdio>#include<map>#include<algorithm>#define Maxn 112345using namespace std;typedef long long LL;LL numbers[Maxn];int dp[Maxn][21]; //dp[i][j]表示从 number[i]开始,长度为2^j次的区间的最值map <int, long long> gg; // first记录gcd值, second 记录相同gcd值下的区间个数int N;void init(){ for (int i = 0; i < N; i++) //dp前的预处理,把数组读进去 dp[i][0] = numbers[i]; for (int j = 1; (1<<j) <= N; j++)//RMQ的初始化操作 { for (int i = 0; i+(1<<j)-1 < N; i++) { dp[i][j] = __gcd (dp[i][j-1], dp[i+(1<<(j-1))][j-1]); } }}int query(int l, int r) // 查询区间最值{ int k = 0; while ((1<<(k+1)) <= r-l+1) k++; return __gcd (dp[l][k], dp[r-(1<<k)+1][k]);}void solve (){ for (int i = 0; i < N; i++) //枚举左端点 { int pos = N-1; while (pos >= i) //二分选定右端点 { int tmp = query(i, pos); int l = i, r = pos; while (r-l > 1) { int mid = (l+r)>>1; if (query(i, mid) == tmp) r = mid; else l = mid; } int cur; if (query(i, l) == tmp) cur = l; else cur = r; gg[tmp] += (pos-cur+1); // 表示区间[i, pos] 与 区间[i, cur+1]的GCD值相等,且等于tmp,所以gcd值等于tmp的数量由pos-cur+1 pos = cur-1; } }}int main(){ int t; cin >> t; int tt = 1; while(t--) { printf ("Case #%d:\n", tt++); gg.clear (); scanf("%d", &N); for(int i=0;i<N;i++) { scanf("%lld", &numbers[i]); } init(); solve (); int Q; scanf("%d", &Q); while (Q--) { int l , r; scanf("%d%d", &l, &r); int ans = query(l-1, r-1); printf ("%d %lld\n", ans, gg[ans]); } } return 0;}
0 0
- RMQ+二分——GCD ( HDU 5726 ) ( 2016 Multi-University Training Contest 1 1004 )
- 2016 Multi-University Training Contest 1 GCD【RMQ+二分】
- 2016 Multi-University Training Contest 1 1004 GCD HDU 5726 (RMQ)
- 2016 Multi-University Training Contest 1 1004 hdu 5726 二分+RMQ
- 2016 Multi-University Training Contest 1-1004---HDU 5726 GCD
- (HDU 5726)2016 Multi-University Training Contest 1 GCD(数学)
- 2016 Multi-University Training Contest 1 1004 GCD
- hdu 5289 Assignment 二分+RMQ 2015 Multi-University Training Contest 1 02
- hdu 5726 GCD(2016 Multi-University Training Contest 1线段树)
- hdu 5726 2016 Multi-University Training Contest 1(二分+dp)
- 2016 Multi-University Training Contest 1-1005---HDU 5727 Necklace(枚举+二分图匹配)
- hdu 5733 tetrahedron(2016 Multi-University Training Contest 1——几何公式题)
- hdu 5723 Abandoned country(2016 Multi-University Training Contest 1——最小生成树+深搜)
- 欧拉定理——PowMod ( HDU 5728 )(2016 Multi-University Training Contest 1 1006)
- 2014 Multi-University Training Contest 1 - 1004 / hdu 4864 Task
- (HDU 5733)2016 Multi-University Training Contest 1 tetrahedron(几何)
- 2016 Multi-University Training Contest 1 1002 hdu 5724 博弈
- 2016 Multi-University Training Contest 1 C Game(hdu 5725)
- CALayer简单的时钟动画
- 关于Fragment中定义一个ListView,然后给这个ListView添加header(ViewPager)的问题
- C++中的static
- 关于java注解使用的例子
- 隐马尔科夫模型(HMMs)之二:隐含模式
- RMQ+二分——GCD ( HDU 5726 ) ( 2016 Multi-University Training Contest 1 1004 )
- 互联网数据库架构设计思路
- 写给刚接触c/c++语言的新人。
- EventBus 3 [
- 最近的思考
- STL之Vector(二):Vector常用函数
- PHP工程师面试常见问题
- 从程序员到事业单位再到公务员的一点感想
- 解决ie6png透明的方法小结