HDU 5869 Different GCD Subarray Query 树状数组+离线
Problem Description
This is a simple problem. The teacher gives Bob a list of problems about GCD (Greatest Common Divisor). After studying some of them, Bob thinks that GCD is so interesting. One day, he comes up with a new problem about GCD. Easy as it looks, Bob cannot figure it out himself. Now he turns to you for help, and here is the problem:
Given an array a of N positive integers a1,a2,⋯aN−1,aN; a subarray of a is defined as a continuous interval between a1 and aN. In other words, ai,ai+1,⋯,aj−1,aj is a subarray of a, for 1≤i≤j≤N. For a query in the form (L,R), tell the number of different GCDs contributed by all subarrays of the interval [L,R].
Input
There are several tests, process till the end of input.
For each test, the first line consists of two integers N and Q, denoting the length of the array and the number of queries, respectively. N positive integers are listed in the second line, followed by Q lines each containing two integers L,R for a query.
You can assume that
1≤N,Q≤100000
1≤ai≤1000000
Output
For each query, output the answer in one line.
Sample Input
5 3
1 3 4 6 9
3 5
2 5
1 5
Sample Output
6
6
6
**题意:**给你n个数Q个查询,每次查询询问[l,r]内不同gcd的个数
**思路:**Q很大,按照一般思路使用线段树在线操作似乎不可行,所以考虑使用离线操作。但重点在于如何预处理出GCD。
在这里我们固定右端点,枚举上一个端点所存的所有不同GCD值,求GCD,并记录不同的,延伸右端点时,再重复操作即可。
在树状数组更新时,当出现一个重复的GCD值,始终把标记维护到最靠右的,并把之前出现的相同GCD的位置所在的标记消掉。这样就能使数量数组拥有前缀特性,可以使用sum[r]-sum[l]了
容器套容器很好用阿,弱要加快学了。
/** @Date : 2016-11-13-16.10
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version :
*/
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <stack>
#include <queue>
#define pii pair<int , int>
#define FF first
#define SS second
#define MP(x,y) make_pair((x), (y))
#define LL long long
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e5+2000;
int n,q;
int c[N];
int a[N];
int ans[N];
vector< pair<int,int> >gp[N];
int vis[1000010];
struct yuu
{
int l, r;
int m;
}Q[N];
int cmp(yuu a, yuu b)
{
return a.r < b.r;
}
int gcd(int a, int b)
{
return b?gcd(b, a % b):a;
}
void add(int x, int y)
{
while(x < N)
{
c[x] += y;
x += x & (-x);
}
}
int sum(int x)
{
int ans = 0;
while(x)
{
ans += c[x];
x -= x & (-x);
}
return ans;
}
void init()
{
MMF(c);
MMF(vis);
MMF(ans);
for(int i = 1; i <= n; i++)
{
int x = a[i];
int p = i;
for(int j = 0; j < gp[i-1].size(); j++)
{
int g = gcd(gp[i-1][j].FF, x);
if(x != g)
{
gp[i].push_back(MP(x, p));
x = g;
p = gp[i-1][j].SS;
}
}
gp[i].push_back(MP(x, p));
}
}
int main()
{
while(~scanf("%d%d", &n, &q))
{
MMF(a);
for(int i = 1; i <= n; i++ )
{
scanf("%d", a + i);
gp[i].clear();
}
init();
for(int i = 0; i < q; i++)
{
scanf("%d%d", &Q[i].l, &Q[i].r);
Q[i].m = i;
}
sort(Q, Q + q, cmp);
//////
int pos = 0;
for(int i = 1; i <= n; i++)
{
for(int j = 0; j < gp[i].size(); j++)//
{
if(vis[gp[i][j].FF])
add(vis[gp[i][j].FF], -1);
vis[gp[i][j].FF] = gp[i][j].SS;
add(gp[i][j].SS, 1);
}
while(Q[pos].r == i)
{
ans[Q[pos].m] = sum(Q[pos].r) - sum(Q[pos].l-1);
pos++;
}
}
for(int i = 0; i < q; i++)
printf("%d\n", ans[i]);
}
return 0;
}
HDU 5869 Different GCD Subarray Query 树状数组+离线的更多相关文章
- HDU 5869 Different GCD Subarray Query 树状数组 + 一些数学背景
http://acm.hdu.edu.cn/showproblem.php?pid=5869 题意:给定一个数组,然后给出若干个询问,询问[L, R]中,有多少个子数组的gcd是不同的. 就是[L, ...
- HDU 5869 Different GCD Subarray Query rmq+离线+数状数组
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5869 Different GCD Subarray Query Time Limit: 6000/3 ...
- HDU 5869 Different GCD Subarray Query (GCD种类预处理+树状数组维护)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5869 问你l~r之间的连续序列的gcd种类. 首先固定右端点,预处理gcd不同尽量靠右的位置(此时gc ...
- HDU 5869 Different GCD Subarray Query 离线+树状数组
Different GCD Subarray Query Problem Description This is a simple problem. The teacher gives Bob a ...
- HDU 5869 Different GCD Subarray Query(2016大连网络赛 B 树状数组+技巧)
还是想不到,真的觉得难,思路太巧妙 题意:给你一串数和一些区间,对于每个区间求出区间内每段连续值的不同gcd个数(该区间任一点可做起点,此点及之后的点都可做终点) 首先我们可以知道每次添加一个值时gc ...
- HDU 5869 Different GCD Subarray Query
离线操作,树状数组,$RMQ$. 这个题的本质和$HDU$ $3333$是一样的,$HDU$ $3333$要求计算区间内不同的数字有几个. 这题稍微变了一下,相当于原来扫描到$i$的之后是更新$a[i ...
- hdu 5869 Different GCD Subarray Query BIT+GCD 2016ICPC 大连网络赛
Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K ( ...
- HDU 4630 No Pain No Game 树状数组+离线查询
思路参考 这里. #include <cstdio> #include <cstring> #include <cstdlib> #include <algo ...
- 【刷题】HDU 5869 Different GCD Subarray Query
Problem Description This is a simple problem. The teacher gives Bob a list of problems about GCD (Gr ...
随机推荐
- 关于css的总结
写在前面 ,学好css,需要长期的推敲和积累 ,细节是不断完善的,逐渐形成自己的风格 让自己的css更加接近优雅. 下面来总结一些我觉得比较好的css代码风格 : 1. 一般网页中的背景 用 ...
- 2017-2018-2 20172314 『Java程序设计』课程 结对编程练习_四则运算
相关过程截图 截图为我负责的部分关于计算的测试 关键代码解释 根据代码中的部分解释,这部分代码实现了结果的整数和分数的输出,如果算出的结果为一个真分数,就输出真分数的形式,如果结果为整数,就输出整数形 ...
- FZU.Software Engineering1816 · First Homework -Preparation
Introduction 041602204 : 我是喜欢狗狗(particularly Corgi & Shiba Inu.)的丁水源 : 我的爱好是音乐.电影.英语(100%!!!!).吉 ...
- 深入了解View的绘制流程
1. ViewRoot ViewRoot是连接WindowManager与DecorView的纽带,View的整个绘制流程的三大步(measure.layout.draw)都是通过ViewRoot完 ...
- C# 创建Excel或需不安装Office
第一种.Aspose.Cells.dll //如果需要饶过office Excel那么就看我最后的实现方法吧~! //我最后的实现是使用的第三方Aspose.Cells.dll //具了解这个dll一 ...
- [OS] 操作系统常考知识点
转自:http://jennica.space/2017/03/21/os-principle/ 大纲如下: 1.操作系统概述2.操作系统运行环境3.进程线程模型4.处理器调度5.同步机制6.存储模型 ...
- [剑指Offer] 47.求1+2+3+...+n
题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). [思路]用&&的短路思想来求和 ...
- query 获取本身的HTML
<div class="test"><p>hello,你好!</p></div> <script> $(".t ...
- snmpwalk的报文检测
1.先用nc起一个监听的端口,然后看报文是不是正确的: 注:nc是一个模拟各种网络协议的东西,模拟服务器.客户端等: 2.触发告警,让他发报文: 3.用nc模拟一个服务端,启动一个udp的端口163: ...
- wmware的vmnet0、vmnet1、vmnet8
用vmware安装虚拟机后会出现三种网卡: 1.vmnet0:桥接网卡,虚拟机相当于一台实体机,可以自用访问与被访问及上网. 在桥接模式下,VMware虚拟出来的操作系统就像是局域网中的一独立的主机, ...