title Link:codeforces 301D
Test Instructions Analysis:
Give you n, m two number, 1?≤?n,?m?≤?2e5,n represents n different numbers, and these numbers are between the interval [1, n], which means that 1~n each number appears once. M for M queries, the query format is two integers x, y, ask you how many logarithm a is between interval [x, y], B satisfies a%b==0.
Problem Solving Ideas:
Inspection point is the frequent access to the interval, immediately think of line tree and tree array, line segment tree is too difficult to write, do not consider, say a tree-like array of ideas.
1) offline processing : All socialize are read and processed in a specific order. In order for the tree-like array to be true and to belong to this interval, there is no disturbance of the interval, we order the interval by the left boundary of the interval, and the left border is processed first:
a,query b){ returna.x>b.x;}
2) preprocessing: Find all divisible numbers with AI, stored in a vector according to the size of the index:
for(int i=1;i<=n;i++){ for(int j=a[i];j<=n;j+=a[i]) { if(p[j]>=i) vec[i].push_back(p[j]); else vec[p[j]].push_back(i); }}
3) tree-like array processing: There is a virtual array cnt
First, there is a Maxx variable to record what is currently processed (right-to-left processing, initial value of n+1), to avoid the effect of repeated calculations. Put all the added value first, in summation, if it has already been added, do not add, here need Maxx to judge:
intmaxx=n+1; for(intI=0;i<m; i++) {int x=Q[i].x,y=Q[i].y, Len; for(intj=x; j<maxx;j++) {len=VEC[J].size (); for(intk=0; k<len;k++) Add (VEC[j] [K],1); } ans[Q[i]. Id]=sum (y);//Sum maxx=x;}
AC Code:
#include <vector>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace Std;intNm, a[200005],p[200005],bit[200005],ans[200005];vector<int>VEC[200005];struct query{intIdx,y;}q[200005]; bool CMP (query A,query b) {returnA.x>b.x;}intLowbit (intNUM) {returnnum& (-num);}intSumint Index){intres=0; for(intI=Index;i>0; I-=lowbit (i)) res+=bit[i];returnRes;} void Add (int Index,intDelta) { for(intI=Index; I<=n;i+=lowbit (i)) Bit[i]+=delta;}intMain () {scanf ("%d %d",&n,&m); for(intI=1; i<=n;i++) {scanf ("%d", &a[i]); P[a[i]]=i; } for(intI=1; i<=n;i++) { for(intJ=a[i];j<=n;j+=a[i]) {if(p[j]>=i)VEC[I].push_back (P[j]);Else VEC[P[j]].push_back (i); } } for(intI=0;i<m; i++) {scanf ("%d %d",&Q[i].x,&Q[i].y);if(Q[i].y<Q[i].x) Swap (Q[i].x,Q[i].y);Q[i]. id=i; }Sort(Q,Q+m, CMP);intmaxx=n+1; for(intI=0;i<m; i++) {int x=Q[i].x,y=Q[i].y, Len; for(intj=x; j<maxx;j++) {len=VEC[J].size (); for(intk=0; k<len;k++) Add (VEC[j] [K],1); } ans[Q[i]. Id]=sum (y); maxx=x; } for(intI=0;i<m; i++)printf("%d\ n", Ans[i]);return 0;}
Summary:
1, off-line processing + tree-like array
2. Notice how the query is sorted
Codeforces 301D (tree-like array)