【HDU 5875】Function

传送门

题目描述

The shorter, the simpler. With this problem, you should be convinced of this truth.
  
You are given an array A of N postive integers, and M queries in the form (l,r).

A function F(l,r) (1lrN) is defined as:

qwq


You job is to calculate F(l,r), for each query (l,r).

解题思路

我们转化一下题意,询问区间(l ,r)其实就是询问al % al+1 %al+2 %.....%ar 的值,那么,在不断取模的过程中,当前的结果一定是不断变小的,并且如果我们对一个数膜一个比它更大的数,显然这个数是不会变的,也就是说,比当前结果大的数其实对我们没有卵用,所以我们的任务就是在当前位置的后面找到第一个比当前数小的数。 那么,我们应该怎么做呢?

XJH大佬直接给出了做法——st表加二分。我们先维护一个区间最小的st表,然后不断二分,如果当前区间的最小值比当前结果小,那么r=m,否则 l=m+1。我们不断重复操作,那么我们最后就可以得到结果。

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int st[100050][25],a[100050];
 7 int loog[100050];
 8 int INF=1000000000;
 9 int t,n,m;
10 inline void read(int &x){
11     x=0; register char ch=getchar();
12     while(ch<'0'||ch>'9')ch=getchar();
13     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
14 }
15 inline int query(int x,int y){
16     int z=loog[y-x+1];
17     return min(st[x][z],st[y-(1<<z)+1][z]);
18 }
19 int main(){
20     loog[0]=-1;
21     for(register int i=1;i<=100000;i++)loog[i]=loog[i>>1]+1;
22     read(t);
23     for(register int cas=1;cas<=t;cas++){
24         for(register int i=0;i<=100000;i++){
25             for(register int j=0;j<=24;j++){
26                 st[i][j]=INF;
27             }
28         }
29         read(n);
30         int N=loog[n]+1;
31         for(register int i=1;i<=n;i++){
32             read(a[i]);
33             st[i][0]=a[i];
34         }
35         for(register int i=1;i<=N;i++){
36             for(register int j=1;j<=n-(1<<i)+1;j++){
37                 st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
38             }
39         }
40         read(m);
41         register int l,r;
42         for(register int i=1;i<=m;i++){
43             read(l),read(r);
44             int num=a[l];
45             l++;
46             while(l<=r&&query(l,r)<=num){
47                 int tr=r;
48                 while(l<tr){
49                     int m=(l+tr)>>1;
50                     if(query(l,m)<=num){
51                         tr=m;
52                     }
53                     else l=m+1;
54                 }
55                 num%=a[l];
56                 l++;
57             }
58             printf("%d\n",num);
59         }
60     }
61 }

猜你喜欢

转载自www.cnblogs.com/Fang-Hao/p/9090119.html