Time Limit: 7000/3500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 976 Accepted Submission(s): 375Problem DescriptionThe shorter, the simpler. With this problem, you should be convinced of this truth.
You are given an array ).
InputThere are multiple test cases.
The first line of input contains a integer ), representing a query.
OutputFor each query) on one line.
Sample Input1 3 2 3 3 1 1 3
Sample Output2
Source
Recommend
Statistic | Submit | Discuss | Note
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5875
题目大意:
N个数(N<=100000),M个询问,每次询问L,R,求F(L,R)。
F(L,R)=F(L,R-1)%A[R] , L<R
=A[L] , L=R
题目思路:
【倍增】
这题数据水到暴力居然过了。。比赛的时候一想会T就没写。
首先这题实际是求A[L]%A[L+1]%A[L+2]...%A[R]的值。
那么很容易想到A[L]右边比他大的数都是没有必要取模的,变为找L右边第一个小于A[L]的取模
模完后的结果缩小,再次寻找当前位置右边第一个小于此时的值的继续取模。可以证明这样的取模次数为log2N(100000取模后最大为49999)
暴力的做法就是预处理的时候直接从后往前用单调栈求出位置X右边第一个小于A[X]的位置Y,next[X]=Y。查询的时候用next跳着模。
当然这是不够的,因为可以构造出递减序列使得实际操作次数仍为N。
用倍增的思想,对于位置i右侧的最长下降子序列,next[i][j]表示位置i右边第2j个的位置,预处理出每个位置的next数组
每次做的时候尽量远跳,直到找到next[j][0]恰好小于当前的值z,则z对A[next[j][0]]取模,移动左标记,继续查找,直到超出R或者没有更小的数。
倍增:
1 // 2 //by coolxxx 3 //#include<bits/stdc++.h> 4 #include<iostream> 5 #include<algorithm> 6 #include<string> 7 #include<iomanip> 8 #include<map> 9 #include<stack> 10 #include<queue> 11 #include<set> 12 #include<bitset> 13 #include<memory.h> 14 #include<time.h> 15 #include<stdio.h> 16 #include<stdlib.h> 17 #include<string.h> 18 //#include<stdbool.h> 19 #include<math.h> 20 #define min(a,b) ((a)<(b)?(a):(b)) 21 #define max(a,b) ((a)>(b)?(a):(b)) 22 #define abs(a) ((a)>0?(a):(-(a))) 23 #define lowbit(a) (a&(-a)) 24 #define sqr(a) ((a)*(a)) 25 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b)) 26 #define mem(a,b) memset(a,b,sizeof(a)) 27 #define eps (1e-10) 28 #define J 10000 29 #define mod 1000000007 30 #define MAX 0x7f7f7f7f 31 #define PI 3.14159265358979323 32 #pragma comment(linker,"/STACK:1024000000,1024000000") 33 #define N 100004 34 #define M 18 35 using namespace std; 36 typedef long long LL; 37 double anss; 38 LL aans; 39 int cas,cass; 40 int n,m,lll,ans; 41 int a[N],s[N]; 42 int nextt[N][M]; 43 void init() 44 { 45 int i,j,k,top; 46 s[top=1]=n; 47 for(i=0;i<M;i++)nextt[n][i]=n+1; 48 for(i=n-1;i;i--) 49 { 50 while(top && a[i]<a[s[top]])top--; 51 if(!top)nextt[i][0]=n+1; 52 else nextt[i][0]=s[top]; 53 s[++top]=i; 54 } 55 for(j=1;j<M;j++) 56 { 57 for(i=1;i<n;i++) 58 { 59 k=nextt[i][j-1]; 60 nextt[i][j]=nextt[k][j-1]; 61 } 62 } 63 } 64 int work(int l,int r) 65 { 66 int i,j,z=a[l]; 67 if(l==r)return z; 68 while(l<r) 69 { 70 if(!z)return z; 71 for(i=0;i<M-1;i++) 72 { 73 if(a[nextt[l][0]]<=z || nextt[l][i]>r)break; 74 if(a[nextt[l][i+1]]<=z || nextt[l][i+1]>r) 75 { 76 l=nextt[l][i]; 77 i=-1; 78 continue; 79 } 80 } 81 if(i==M || nextt[l][i]>r || !a[nextt[l][i]])return z; 82 z%=a[nextt[l][0]];l=nextt[l][0]; 83 } 84 return z; 85 } 86 int main() 87 { 88 #ifndef ONLINE_JUDGE 89 // freopen("1.txt","r",stdin); 90 // freopen("2.txt","w",stdout); 91 #endif 92 int i,j,k; 93 int x,y,z; 94 // init(); 95 for(scanf("%d",&cass);cass;cass--) 96 // for(scanf("%d",&cas),cass=1;cass<=cas;cass++) 97 // while(~scanf("%s",s)) 98 // while(~scanf("%d",&n)) 99 { 100 scanf("%d",&n); 101 for(i=1;i<=n;i++)scanf("%d",a+i); 102 init(); 103 scanf("%d",&m); 104 for(i=1;i<=m;i++) 105 { 106 scanf("%d%d",&x,&y); 107 printf("%d\n",work(x,y)); 108 } 109 } 110 return 0; 111 } 112 /* 113 // 114 115 // 116 */