HDU - 5869 Different GCD Subarray Query 树状数组离线处理
2017-09-02 23:45
465 查看
传送门:HDU5869
题意:给出一个长度为n的序列和m次询问,每次询问给出l,r,求[l, r]区间内所有子序列不同gcd的个数。
思路:首先明确对于一个序列a[l...r]的所有以a[l]开头的子序列,所能得到的不同gcd的个数最多有log(a[l])个。那么这个题中我们就可以对于每一个位置,预处理出以该位置为结尾的所有不同gcd的最大左边界(即L至少要到这个位置才能在L~R这个区间中能形成这个gcd),然后将所有询问按右端点排序,每次处理询问的时候将所有小于r的位置预处理出来的值用树状数组维护一下就好了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int> P;
const int MAXN = 1000100;
struct node{
int l, r, id;
bool operator < (node a) const
{
return r < a.r;
}
}Q[MAXN];
int bit[MAXN], a[MAXN];
void add(int i, int x)
{
while(i < MAXN)
{
bit[i] += x;
i += i & -i;
}
}
int sum(int i)
{
int res = 0;
while(i)
{
res += bit[i];
i -= i & -i;
}
return res;
}
vector<P> gcd[MAXN];
int book[MAXN], ans[MAXN];
int main()
{
int n, q, tmp, id;
while(cin >> n >> q)
{
memset(book, 0, sizeof(book));
memset(bit, 0, sizeof(bit));
for(int i = 1; i <= n; i++)
scanf("%d", a + i), gcd[i].clear();
for(int i = 1; i <= n; i++)
{
gcd[i].push_back(P(a[i], i));
for(int j = 0; j < gcd[i - 1].size(); j++)
{
tmp = __gcd(a[i], gcd[i - 1][j].first);
if(tmp != gcd[i][gcd[i].size() - 1].first)
gcd[i].push_back(P(tmp, gcd[i - 1][j].second));
}
}
for(int i = 0; i < q; i++)
scanf("%d %d", &Q[i].l, &Q[i].r), Q[i].id = i;
sort(Q, Q + q);
int last = 1;
for(int i = 0; i < q; i++)
{
while(last <= Q[i].r)
{
for(int j = 0; j < gcd[last].size(); j++)
{
tmp = gcd[last][j].first;
id = gcd[last][j].second;
if(book[tmp])
{
if(book[tmp] < id)
{
add(book[tmp], -1);
add(id, 1);
book[tmp] = id;
}
}
else
{
add(id, 1);
book[tmp] = id;
}
}
last++;
}
ans[Q[i].id] = sum(Q[i].r) - sum(Q[i].l - 1);
}
for(int i = 0; i < q; i++)
printf("%d\n", ans[i]);
}
return 0;
}
题意:给出一个长度为n的序列和m次询问,每次询问给出l,r,求[l, r]区间内所有子序列不同gcd的个数。
思路:首先明确对于一个序列a[l...r]的所有以a[l]开头的子序列,所能得到的不同gcd的个数最多有log(a[l])个。那么这个题中我们就可以对于每一个位置,预处理出以该位置为结尾的所有不同gcd的最大左边界(即L至少要到这个位置才能在L~R这个区间中能形成这个gcd),然后将所有询问按右端点排序,每次处理询问的时候将所有小于r的位置预处理出来的值用树状数组维护一下就好了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int> P;
const int MAXN = 1000100;
struct node{
int l, r, id;
bool operator < (node a) const
{
return r < a.r;
}
}Q[MAXN];
int bit[MAXN], a[MAXN];
void add(int i, int x)
{
while(i < MAXN)
{
bit[i] += x;
i += i & -i;
}
}
int sum(int i)
{
int res = 0;
while(i)
{
res += bit[i];
i -= i & -i;
}
return res;
}
vector<P> gcd[MAXN];
int book[MAXN], ans[MAXN];
int main()
{
int n, q, tmp, id;
while(cin >> n >> q)
{
memset(book, 0, sizeof(book));
memset(bit, 0, sizeof(bit));
for(int i = 1; i <= n; i++)
scanf("%d", a + i), gcd[i].clear();
for(int i = 1; i <= n; i++)
{
gcd[i].push_back(P(a[i], i));
for(int j = 0; j < gcd[i - 1].size(); j++)
{
tmp = __gcd(a[i], gcd[i - 1][j].first);
if(tmp != gcd[i][gcd[i].size() - 1].first)
gcd[i].push_back(P(tmp, gcd[i - 1][j].second));
}
}
for(int i = 0; i < q; i++)
scanf("%d %d", &Q[i].l, &Q[i].r), Q[i].id = i;
sort(Q, Q + q);
int last = 1;
for(int i = 0; i < q; i++)
{
while(last <= Q[i].r)
{
for(int j = 0; j < gcd[last].size(); j++)
{
tmp = gcd[last][j].first;
id = gcd[last][j].second;
if(book[tmp])
{
if(book[tmp] < id)
{
add(book[tmp], -1);
add(id, 1);
book[tmp] = id;
}
}
else
{
add(id, 1);
book[tmp] = id;
}
}
last++;
}
ans[Q[i].id] = sum(Q[i].r) - sum(Q[i].l - 1);
}
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(离线处理+树状数组)
- [区间GCD预处理 树状数组 离线] HDU 5869 Different GCD Subarray Query
- HDU 5869 Different GCD Subarray Query(离线+gcd)
- HDU 5869 Different GCD Subarray Query 离线+树状数组
- hdu-5869 Different GCD Subarray Query gcd预处理 + 树状数组 + 离线
- HDU 5869 Different GCD Subarray Query 离线 树状数组
- HDU 5869 Different GCD Subarray Query [区间gcd预处理+离线]【数据结构】
- hdu 5869 Different GCD Subarray Query 预处理 + 离线
- Different GCD Subarray Query HDU - 5869 (gcd处理+离线线段树·)
- hdu 5869 Different GCD Subarray Query 离线+树状数组
- HDU 5869 Different GCD Subarray Query (数学gcd+树状数组离线查询)
- HDU 5869 Different GCD Subarray Query 树状数组 + 一些数学背景
- HDU 5869 Different GCD Subarray Query
- HDU 5869 Different GCD Subarray Query(2016大连网络赛 B 树状数组+技巧)
- HDU 5869 Different GCD Subarray Query
- hdu5869——Different GCD Subarray Query(思考+树状数组)
- hdu5869——Different GCD Subarray Query(思考+树状数组)
- 2016 大连网络赛 hdu 5869 Different GCD Subarray Query(gcd+树状数组)★ ★
- HDU - 5869 Different GCD Subarray Query GCD+离线+树状数组(区间不同gcd的个数)