O(n*logn)预处理出对于每个位置i,最大的left[i], right[i], 使得arr[left[i]...i...right[i]]与arr[i]互质(当然arr[i]与其本身不互质不考虑),利用链表记录一些信息,然后用树状数组维护后缀和,更新答案。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> #include <bitset> #include <iomanip> //#pragma comment(linker, "/STACK:102400000,102400000") using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::stringstream; using std::make_pair; using std::getline; using std::greater; using std::endl; using std::multimap; using std::deque; using std::unique; using std::lower_bound; using std::random_shuffle; using std::bitset; using std::upper_bound; using std::multiset; using std::ios; typedef long long LL; typedef unsigned long long ULL; typedef unsigned UN; typedef pair<ULL, ULL> PAIR; typedef multimap<int, int> MMAP; typedef long double LF; const int MAXN(200010); const int MAXM(310); const int MAXE(310); const int MAXK(6); const int HSIZE(131313); const int SIGMA_SIZE(26); const int MAXH(18); const int INFI((INT_MAX-1) >> 1); const ULL BASE(31); const LL LIM(1e13); const int INV(-10000); const int MOD(1000000007); const double EPS(1e-7); const LF PI(acos(-1.0)); template<typename T> inline void checkmax(T &a, T b){if(b > a) a = b;} template<typename T> inline void checkmin(T &a, T b){if(b < a) a = b;} template<typename T> inline T ABS(const T &a){return a < 0? -a: a;} struct BIT { int arr[MAXN], size; void init(int s) { size = s; memset(arr+1, 0, sizeof(arr[0])*s); } void updata(int ti, int tv) { for(; ti > 0; ti -= ti&-ti) arr[ti] += tv; } int query(int ti) { int ret = 0; for(; ti <= size; ti += ti&-ti) ret += arr[ti]; return ret; } } bt; struct EDGE { int u, v; EDGE *next; }; bool is[MAXN]; EDGE *rec[MAXN]; EDGE eg1[600100], *rear1; void prepro() { memset(is, -1, sizeof(is)); is[1] = false; for(LL i = 2; i <= 200000; ++i) if(is[i]) { rear1->v = i; rear1->next = rec[i]; rec[i] = rear1++; for(LL j = i+i; j <= 200000; j += i) { rear1->v = i; rear1->next = rec[j]; rec[j] = rear1++; is[j] = false; } } } int aid[MAXN], left[MAXN], right[MAXN]; int arr[MAXN]; EDGE *que[MAXN]; EDGE eg2[MAXN], *rear2; EDGE *tab[MAXN]; EDGE eg3[MAXN], *rear3; int ans[MAXN]; int main() { // freopen("d:\\in.txt","r",stdin); // freopen("d:\\out.txt","w",stdout); rear1 = eg1; prepro(); int n, m; while(scanf("%d%d", &n, &m), n+m) { rear2 = eg2; rear3 = eg3; int temp = 1; for(int i = 1; i <= n; ++i) { scanf("%d", arr+i); que[i] = tab[i] = 0; checkmax(temp, arr[i]); } for(int i = 0; i <= temp; ++i) aid[i] = 0; for(int i = 1; i <= n; ++i) { int mx = 0; for(EDGE *p = rec[arr[i]]; p; p = p->next) { checkmax(mx, aid[p->v]); aid[p->v] = i; } left[i] = mx+1; } for(int i = 0; i <= temp; ++i) aid[i] = n+1; for(int i = n; i >= 1; --i) { int mi = n+1; for(EDGE *p = rec[arr[i]]; p; p = p->next) { checkmin(mi, aid[p->v]); aid[p->v] = i; } right[i] = mi-1; rear3->u = left[i]; rear3->v = i; rear3->next = tab[right[i]]; tab[right[i]] = rear3++; } int ql, qr; for(int i = 0; i < m; ++i) { scanf("%d%d", &ql, &qr); rear2->u = ql; rear2->v = i; rear2->next = que[qr]; que[qr] = rear2++; } bt.init(n); for(int i = 1; i <= n; ++i) //更新答案时保证qr <= right[i] { if(left[i] > 1) bt.updata(left[i]-1, -1); bt.updata(i, 1); for(EDGE *p = que[i]; p; p = p->next) ans[p->v] = bt.query(p->u); for(EDGE *p = tab[i]; p; p = p->next) //对于qr > right[k]的询问, arr[k]不会再有贡献了,所以修改回去 { if(p->u > 1) bt.updata(p->u-1, 1); bt.updata(p->v, -1); } } for(int i = 0; i < m; ++i) printf("%d\n", ans[i]); } return 0; }