HDU 5875 Function 2016 ACM/ICPC Asia Regional Dalian Online
N个数(N<=100000),M个询问,每次询问L,R,求F(L,R)。
F(L,R)=F(L,R-1)%A[R] , L<R
这道题数据比较鶸 可以直接用递减爆 正确做法应该是倍增
用倍增的思想,对于位置i右侧的最长下降子序列,next[i][j]表示位置i右边第2j个的位置,预处理出每个位置的next数组
每次做的时候尽量远跳,直到找到next[j][0]恰好小于当前的值z,则z对A[next[j][0]]取模,移动左标记,继续查找,直到超出R或者没有更小的数
// //by coolxxx //#include<bits/stdc++.h> #include<iostream> #include<algorithm> #include<string> #include<iomanip> #include<map> #include<stack> #include<queue> #include<set> #include<bitset> #include<memory.h> #include<time.h> #include<stdio.h> #include<stdlib.h> #include<string.h> //#include<stdbool.h> #include<math.h> #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) #define abs(a) ((a)>0?(a):(-(a))) #define lowbit(a) (a&(-a)) #define sqr(a) ((a)*(a)) #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b)) #define mem(a,b) memset(a,b,sizeof(a)) #define eps (1e-10) #define J 10000 #define mod 1000000007 #define MAX 0x7f7f7f7f #define PI 3.14159265358979323 #pragma comment(linker,"/STACK:1024000000,1024000000") #define N 100004 #define M 18 using namespace std; typedef long long LL; double anss; LL aans; int cas,cass; int n,m,lll,ans; int a[N],s[N]; int nextt[N][M]; void init() { int i,j,k,top; s[top=1]=n; for(i=0;i<M;i++)nextt[n][i]=n+1; for(i=n-1;i;i--) { while(top && a[i]<a[s[top]])top--; if(!top)nextt[i][0]=n+1; else nextt[i][0]=s[top]; s[++top]=i; } for(j=1;j<M;j++) { for(i=1;i<n;i++) { k=nextt[i][j-1]; nextt[i][j]=nextt[k][j-1]; } } } int work(int l,int r) { int i,j,z=a[l]; if(l==r)return z; while(l<r) { if(!z)return z; for(i=0;i<M-1;i++) { if(a[nextt[l][0]]<=z || nextt[l][i]>r)break; if(a[nextt[l][i+1]]<=z || nextt[l][i+1]>r) { l=nextt[l][i]; i=-1; continue; } } if(i==M || nextt[l][i]>r || !a[nextt[l][i]])return z; z%=a[nextt[l][0]];l=nextt[l][0]; } return z; } int main() { #ifndef ONLINE_JUDGE // freopen("1.txt","r",stdin); // freopen("2.txt","w",stdout); #endif int i,j,k; int x,y,z; // init(); for(scanf("%d",&cass);cass;cass--) // for(scanf("%d",&cas),cass=1;cass<=cas;cass++) // while(~scanf("%s",s)) // while(~scanf("%d",&n)) { scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",a+i); init(); scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); printf("%d\n",work(x,y)); } } return 0; } /* // // */