HDU 5875 Function(RMQ-ST+二分)

Function

Time Limit: 7000/3500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2427    Accepted Submission(s): 858

Problem Description
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:
F(l,r)={AlF(l,r1) modArl=r;l<r.
You job is to calculate F(l,r), for each query (l,r).
 
Input
There are multiple test cases.
  
  The first line of input contains a integer T, indicating number of test cases, and T test cases follow. 
  
  For each test case, the first line contains an integer N(1N100000).
  The second line contains N space-separated positive integers: A1,,AN (0Ai109).
  The third line contains an integer M denoting the number of queries. 
  The following M lines each contain two integers l,r (1lrN), representing a query.
 
Output
For each query(l,r), output F(l,r) on one line.
 
Sample Input
1
3
2 3 3
1
1 3
 
Sample Output
2

题目链接:HDU 5875

题意就是给定区间[L,R],求A[L]%A[L+1]%A[L+2]%……%A[R]的值,这里有一个技巧,可以发现在b>a时,a%b是无意义的,即结果还是a,因此把取模过程改一下,每一次从当前位置idx向右二分找到第一个值小于A[idx]的数,然后对它取模,然后这样迭代地继续寻找,直到在idx~r中找不到这样的位置即可。对了这题其实最大的意义是让我知道了log类函数常数比较大,一开始交用这个函数超时,不管是log2还是log都这样,因此用位运算模拟来求这个指数k。

代码:

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 100007;
int arr[N], Min[N][18];

int Scan()
{
    int res = 0, ch, flag = 0;

    if ((ch = getchar()) == '-')            //判断正负
        flag = 1;

    else if (ch >= '0' && ch <= '9')          //得到完整的数
        res = ch - '0';
    while ((ch = getchar()) >= '0' && ch <= '9' )
        res = (res << 3) + (res << 1) + ch - '0';

    return flag ? -res : res;
}
void RMQ_init(int l, int r)
{
    int i, j;
    for (i = l; i <= r; ++i)
        Min[i][0] = arr[i];
    for (j = 1; l + (1 << j) - 1 <= r; ++j)
        for (i = l; i + (1 << j) - 1 <= r; ++i)
            Min[i][j] = min(Min[i][j - 1], Min[i + (1 << (j - 1))][j - 1]);
}
inline int ST(int l, int r)
{
    int len = r - l + 1;
    int k = 0;
    while (1 << (k + 1) <= len)
        ++k;
    return min(Min[l][k], Min[r - (1 << k) + 1][k]);
}
int getfirstpos(int key, int l, int r)
{
    int L = l, R = r;
    int ans = -1;
    while (L <= R)
    {
        int mid = (L + R) >> 1;
        if (ST(l, mid) <= key)
        {
            ans = mid;
            R = mid - 1;
        }
        else
            L = mid + 1;
    }
    return ans;
}
int main(void)
{
    int tcase, n, m, l, r, i;
    scanf("%d", &tcase);
    while (tcase--)
    {
        scanf("%d", &n);
        getchar();
        for (i = 1; i <= n; ++i)
            arr[i] = Scan();
        RMQ_init(1, n);
        scanf("%d", &m);
        while (m--)
        {
            scanf("%d%d", &l, &r);
            if (l == r)
                printf("%d
", arr[l]);
            else
            {
                int idx = l;
                int res = arr[l];
                int pos;
                while (idx + 1 <= r && ~(pos = getfirstpos(res, idx + 1, r)) && res)
                {
                    res %= arr[pos];
                    idx = pos;
                }
                printf("%d
", res);
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Blackops/p/6662299.html