http://acm.hdu.edu.cn/showproblem.php?pid=5869

Test instructions: Given an array, and then given a number of queries, asking [L, R], how many of the GCD of the subarray are different.

is the GCD value of the different intervals in [L, R], and how many are different.

Give a sample

3 3

7 7 7

1 2

1 3

3 3

Math background:

A number and if n numbers constantly gcd, the result is only loga[i] species, why? Because the a[i] mass factor can be decomposed, the number is loga[i] multiplied by a number. (The smallest number is 2, then loga[i] 2 multiplied also burst a[i])

So, consider the sequence that ends with A[i], how many different gcd can be recorded.

such as examples. In parentheses, the GCD value and the A[i] number are first gcd with that position, and the value is Val,

1, 3, 4, 6, 9

(1, 1) (3, 2) (4, 3) (6, 4) (9, 5)

(1, 1) (1, 2) (2, 3) (3, 4)

(1, 2) (1, 3)//9 this number in [3, 5] All the way gcd, you can get 1

In fact, the left endpoint has been maintained, requiring the left endpoint as large as possible.

1, why to maintain the left end, because the answer gives is [L, R] This interval of the different gcd, if you pre-processing, R and L-1 gcd can not be counted in.

2, ask for the left end point as large as possible, that is because I later to the R sort, as far as possible to r, the result is optimal, (can refer to the method of finding the number of different numbers of intervals.) Then write it back. ）

Then there is the routine. Put the GCD to the left end.?, this is the point, at the beginning I put different gcd to the right end of the plug, this is not right, because toward the end of the plug, r and L-1 GCD will be counted in you, so will WA.

Book[x] Represents the right-most position at which the value of x appears.

#include <cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#defineIOS Ios::sync_with_stdio (False)using namespacestd;#defineINF (0X3F3F3F3F)typedefLong Long intLL; #include<iostream>#include<sstream>#include<vector>#include<Set>#include<map>#include<queue>#include<string>Const intMAXN =1000000+ -;Const intN =1000000+ -;intC[MAXN];intLowbit (intx) {returnX & (-x);}voidUpDate (intPosintval) { while(Pos <= N- -) {C[pos]+=Val; POS+=Lowbit (POS); }}intQueryintPOS) { intAns =0; while(POS) {ans+=C[pos]; POS-=Lowbit (POS); } returnans;}intN, Q;intA[MAXN];structNode {intL, R; intID; BOOL operator< (Const structNode & RHS)Const { returnR <RHS. R }}B[MAXN];intBOOK[MAXN];intANS[MAXN];voidWork () {memset (book,0,sizeofBook ); Memset (c,0,sizeofc); for(inti =1; I <= N; ++i) {scanf ("%d", &A[i]); } for(inti =1; I <= Q; ++i) {scanf ("%d%d", &b[i]. L, &B[i]. R); if(B[i]. L >B[i]. R) Swap (B[i]. L, B[i]. R); B[i].id=i; } sort (b+1, B +1+q); intCur =1;//for (int i = 1; I <= Q; ++i) {//cout << B[i]. L << "" << b[i]. R << Endl;// } for(inti =1; I <= Q; ++i) { for(intj = cur; J <= B[i]. R ++j) {intx =A[cur]; for(intk = cur; K >=1; k--) { if(Book[x] < K) {//The left end point can only be as far as right, on the left, sample: 7 7 7 if(Book[x]) {//The tree array cannot start at 0UpDate (book[x),-1); } Book[x]= k;//different gcd, pressing to the left endUpDate (Book[x],1); }//if (book[x] > K) while (1);//book[x] = k;//upDate (Book[x], 1); if(k = =1) Break; if(x = =1) Break; X= __GCD (x, A[k-1]); } cur++; } Ans[b[i].id]= Query (B[i]. R)-Query (B[i]. L1); } for(inti =1; I <= Q; ++i) {printf ("%d\n", Ans[i]); }}intMain () {#ifdef local freopen ("Data.txt","R", stdin);#endif while(SCANF ("%d%d", &n, &q)! =EOF) work (); return 0;}

View Code

About tree-like arrays

3.1, for reverse order: First of all, the data discretization, because the tree-like array covers the interval is 1-max such, not discrete words can not open so large array. For example, after the discrete is: 5, 2, 1, 4, 3, the idea is: Insert 5,add (5,1), POS 5 is set to 1, and then ans + = i-get_sum (5); **I** **The meaning is that I is currently inserted.** **number** , and then Get_sum () is the current number of less than 5, in fact, is asked 1-5 between the number of numbers, it is certainly smaller than 5. A minus, is about 5 reverse order number. Eg: the number of reverse pairs of 2 is 1 pairs.

LL get_inversion (int a[],int lena)//number of reverse orders

{

ll ans = 0;//reverse is generally a lot, need to use LL

for (int i=1;i<=lena;++i)//a[]={5,2,1,4,3} ans=6;

{//a[]={5,5,5,5,5} ans=0; reverse is strictly greater than

Add (a[i],1); Ans + = I-get_sum (A[i]);

}

return ans;

}

About Data discretization, you can open a structure, save Val and Pos, **and then** **sort** by Val, according to the POS from small to large assignment. for (int i=1;i<=n;++i) a[book[i].pos]=i; From small to large discrete. a[3]=1,a[1]=2, wait.

{9,1,0,5,4} after discretization {5,2,1,4,3}

3.2, solve the interval of the number of different elements, offline algorithm. Complexity O (q + nlog (n))

The meaning of the tree-like array is: 1--pos the number of different elements of this interval. What do you do? is Add (pos,1), in this position +1, that is, the position of the element type +1. Then sort the query in ascending order of R. Because here is the best, I always try to rely on the R, so that the query is not heavy. What do you mean? That is, if there are: 2, 1, 3, 5, 1, 7. At first [1,4] This number is all pressed into the tree array, with the number of groups Book[val], the Val this element appears in the most right position, because we need to delete the duplicate, but also to the right. When you get to pos=5 this position, note that since 1 is the occurrence of book[1] = 2, so what we are going to do is to place 2 of the number of elements in this position-1, which is add (book[1], 1). Then the number of elements that appear in the fifth position is +1, which is add (5,1). Why is it? Because you try to put the kind to the right, because our r is increment, so that you make the query [4,6] possible, because I that 1 joined, not always with pos=2 that position 1, and then, query [4,7] words, the same meaning, because the middle of the 1 came in. So we're trying to get to the right, after all we've sorted the query by R. And this can only be offline, has been preprocessed ans[i] indicates the ans of the first inquiry. After updating to [4,7], it is impossible to query [up], because it is clear that the location of pos=2 has been deleted.

void work ()

{

scanf ("%d", &n);

for (int i=1;i<=n;++i) scanf ("%d", &a[i]);

int q; scanf ("%d", &q);

for (int i=1;i<=q;++i)

{

scanf ("%d%d", &query[i]. L,&query[i]. R);

Query[i].id = i; Record ans

}

Sort (query+1,query+1+q);

int cur = 1;

for (int i=1;i<=q;++i)

{

for (int j=cur;j<=query[i]. R;++J)

{

if (Book[a[j]])

Add (book[a[j]],-1); del this position

Book[a[j]]=j; Update the right-most value for this location

Add (j,1); There's a new element in this position.

}

cur = query[i]. r+1; Indicates that it is now preprocessed to this position. Can't look back, and it won't go back.

Ans[query[i].id] = Get_sum (Query[i]. R)-Get_sum (Query[i]. L-1); Interval subtraction

}

for (int i=1;i<=q;++i)

printf ("%d\n", Ans[i]);

}

HDU 5869 Different GCD subarray Query tree array + some math backgrounds