Loading

「ACM Dalian Online 2016」H.Function(二分+RMQ)


描述

传送门:我是传送门

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) (1≤l≤r≤N) is defined as:

g

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

输入

There are multiple test cases.

The first line of input contains a integer TT, indicating number of test cases, and TTtest cases follow. 

For each test case, the first line contains an integer N(1N100000)N(1≤N≤100000).
The second line contains NN space-separated positive integers: A1,,ANA1,…,AN (0Ai109)(0≤Ai≤109).
The third line contains an integer MM denoting the number of queries.
The following MM lines each contain two integers l,r(1lrN)l,r(1≤l≤r≤N), representing a query.

输出

For each query(l,r)(l,r), output F(l,r)F(l,r) on one line.

样例

输入

1
3
2 3 3
1
1 3

输出

2

思路

一个数比它大的数没有意义,比如10%100、20%30···

每次二分的找到右侧第一个比他小的就好了

代码

/*
 * =================================================================
 *
 *       Filename:  hdu5875.cpp
 *
 *           Link:  http://acm.hdu.edu.cn/showproblem.php?pid=5875
 *
 *        Version:  1.0
 *        Created:  2018/10/09 10时30分42秒
 *       Revision:  none
 *       Compiler:  g++
 *
 *         Author:  杜宁元 (https://duny31030.top/), duny31030@126.com
 *   Organization:  QLU_浪在ACM
 *
 * =================================================================
 */
#include <bits/stdc++.h>
using namespace std;
#define clr(a, x) memset(a, x, sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define pre(i,a,n) for(int i=n;i>=a;i--)
#define ll long long
#define max3(a,b,c) fmax(a,fmax(b,c))
#define ios ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int N = 100050;
int n,q,t,a,x,y;
vector<int> Q;
int dp_min[N][30];
void RMQ_init(const vector<int>& A)
{
    for(int i = 0;i < n;i++)
    {
        dp_min[i][0] = A[i];
    }
    for(int j = 1;(1 << j) <= n;j++)
        for(int i = 0;i + (1 << j) - 1 < n;i++)
        {
            dp_min[i][j] = min(dp_min[i][j-1],dp_min[i+(1 << (j-1))][j-1]);
        }
}

int RMQ_min(int L,int R)
{
    int k = 0;
    while((1 << (k+1)) <= (R-L+1))   // 如果2^(k+1) <= R-L+1,那么k还可以加1
    {
        k++;
    }
    // cout << "min = " << min(dp_min[L][k],dp_min[R-(1 << k)+1][k]) << endl;
    return min(dp_min[L][k],dp_min[R-(1 << k)+1][k]);
}


int main()
{
    ios
#ifdef ONLINE_JUDGE
#else
        freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
#endif
    scanf("%d",&t);
    while(t--)
    {
        Q.clear();
        clr(dp_min,0);
        scanf("%d",&n);
        rep(i,1,n)  {   scanf("%d",&a); Q.push_back(a); }
        RMQ_init(Q);
        scanf("%d",&q);
        rep(i,1,q)
        {
            scanf("%d %d",&x,&y);
            x--,y--;
            int tmp = Q[x];
            if(x == y)
            {
                printf("%d\n",Q[x]);
                continue;
            }
            x++;
            while(x <= y)
            {
                int L= x,R = y;
                int flag = 0;
                while(L < R)
                {
                    int mid = (L+R) >> 1;
                    if(RMQ_min(L,mid) <= tmp)
                        R = mid;
                    else
                        if(RMQ_min(mid+1,R) <= tmp)
                            L = mid+1;
                        else
                        {
                            flag = 1;
                            break;
                        }
                }
                if(flag)    break;
                tmp %= Q[L];
                x = L+1;
            }
            printf("%d\n",tmp);
        }
    }
    fclose(stdin);
    // fclose(stdout);
    return 0;
}

 

posted @ 2021-01-20 21:31  Yiduuannng  阅读(55)  评论(0编辑  收藏  举报