HDU 5875 st+二分区间

Posted 不知姓名的黑猫君

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5875 st+二分区间相关的知识,希望对你有一定的参考价值。

题目大意:给你n个数,q次询问,每次询问区间[l, r],问a[i]%a[i + 1] % a[i + 2]...%a[j](j <= r)的值

思路:st预处理维护,在二分区间,复杂度n*(logn)*logn

 

技术分享
//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
const int maxn = 1e5 + 5;
int a[maxn];
int st[maxn][25];
int n;

void init(){
    for (int i = 0; i < n; i++) st[i][0] = a[i];
    for (int j = 1; (1 << j) <= n; j++){
        for (int i = 0; i + (1 << j) - 1 < n; i++){
            st[i][j] = min(st[i + (1 << (j-1))][j - 1], st[i][j - 1]);
        }
    }
}

inline int query(int l, int r){
    int len = r - l + 1;
    int k = 0;
    while ((1 << (k + 1)) <= len) k++;
    return min(st[l][k], st[r - (1 << k) + 1][k]);
}

inline int solve(){
    int l, r;
    scanf("%d%d", &l, &r);
    l--, r--;
    if (l == r) return a[l];
    int val = a[l];
    ///二分区间
    l++;
    while (l <= r){
        int lb = l, rb = r;
        while (lb < rb){
            int mid = (lb + rb) / 2;
            if (query(lb, mid) <= val) rb = mid;
            else if (query(mid + 1, rb) <= val) lb = mid + 1;
            else return val;
        }
        l = lb + 1;
        val %= a[lb];
    }
    return val;
}

int main(){
    int t; scanf("%d", &t);
    while (t--){
        scanf("%d", &n);
        for (int i = 0; i < n; i++){
            scanf("%d", a + i);
        }
        init();
        int q; scanf("%d", &q);
        while (q--){
            printf ("%d\n", solve());
        }
    }
    return 0;
}
View Code

 

以上是关于HDU 5875 st+二分区间的主要内容,如果未能解决你的问题,请参考以下文章

HDU5875 - Function

Function---hdu5875(大连网选,区间连续求余)

HDU 5875 Function (大连网络赛 H 线段树+gcd)

2016大连网络赛 1008 & hdu5875 (优先队列+离线)=不确定暴力

hdu 6704 K-th occurrence 二分 ST表 后缀数组 主席树

hdu5289 Assignment (区间查询最大值最小值,st算法...)