hdu4777-Rabbit Kingdom
题意:求区间内与其他任何数都互质的数的个数。
题解:求出每个数左右互质的边界。然后对询问排序,通过树状数组求解。
讲道理真的好难啊= =
http://blog.csdn.net/dyx404514/article/details/15507209 这个博客讲的最清楚(竟然是戴神的博客=。= 听过戴神讲splay,现在还不会……
#include <bits/stdc++.h> using namespace std; const int N = 200005; /***素数打表***/ int p[N]; int is_p[N+1]; int cnt_p; void get_p() { for (int i = 0; i <= N; ++i) is_p[i] = 1; cnt_p = is_p[0] = is_p[1] = 0; for (int i = 2; i <= N; ++i) { if (is_p[i]) { p[cnt_p++] = i; for (int j = i * 2; j <= N; j += i) is_p[j] = 0; } } } /***因数分解***/ int fac[N]; // 记录出现的因数 int cal_fac(int x) { int tmp = x; int idx = 0; int i; for (i = 0; p[i] <= tmp/p[i]; ++i) { if (tmp%p[i]) continue; while (tmp%p[i] == 0) tmp /= p[i]; fac[idx++] = p[i]; } if (tmp != 1) fac[idx++] = tmp; return idx; } /***计算每个数互质的最左最右区间***/ int l[N], r[N]; int adj[N]; int a[N]; void cal_inv(int n) { for (int i = 0; i < N; ++i) adj[i] = 0; for (int i = 1; i <= n; ++i) { int cnt = cal_fac(a[i]); l[i] = 0; for (int j = 0; j < cnt; ++j) { l[i] = max(l[i], adj[fac[j]]); adj[fac[j]] = i; } } for (int i = 0; i < N; ++i) adj[i] = n+1; for (int i = n; i >= 1; --i) { r[i] = n+1; int cnt = cal_fac(a[i]); for (int j = 0; j < cnt; ++j) { r[i] = min(r[i], adj[fac[j]]); adj[fac[j]] = i; } } } struct node { int l, r, id; bool operator<(const node x) const { return l < x.l; } } qry[N]; int bit[N]; int lowbit(int x) { return x&-x; } void add(int x, int v, int n) { while(x<=n) bit[x]+=v,x+=lowbit(x); } int sum(int x) { int ans=0; while(x) ans+=bit[x],x-=lowbit(x); return ans; } vector<int> lb[N]; // lb[i] 以i为左边界的数 int ans[N]; int main() { //freopen("in.txt", "r", stdin); get_p(); int n, k; while (~scanf("%d%d", &n, &k)) { if (n == 0) break; for (int i = 1; i <= n; ++i) { scanf("%d", a+i); } cal_inv(n); for (int i = 0; i < k; ++i) { scanf("%d%d", &qry[i].l, &qry[i].r); qry[i].id = i; } sort(qry, qry+k); for (int i = 0; i <= n; ++i) lb[i].clear(); memset(bit, 0, sizeof bit); for (int i = 1; i <= n; ++i) { if (!l[i]) { add(i, 1, n); add(r[i], -1, n); } else lb[l[i]].push_back(i); } int pos = 1; for (int i = 0; i < k; ++i) { while (qry[i].l > pos) { add(pos, -1, n); add(r[pos], 1, n); for (unsigned j = 0; j < lb[pos].size(); ++j) { int x = lb[pos][j]; add(x, 1, n); add(r[x], -1, n); } pos++; } ans[qry[i].id] = sum(qry[i].r)-sum(qry[i].l-1); } for (int i = 0; i < k; ++i) { printf("%d\n", ans[i]); } } return 0; }