zoukankan      html  css  js  c++  java
  • 2016 ACM/ICPC Asia Regional Dalian Online 1008 Function 二分+RMQ

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


    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
     
    题意:给你一个n个数的序列,以及m个查询,每次查询一个区间[l,r],求a[l]%a[l+1]%a[l+2]...%a[r]
    思路:易知,比当前大的数取模没意义,实际取模的次数是log次(取模至少会减少一半),那么问题就转化为如何在所查询的区间跳着来取模,每次只对比当前小的数取模
    iky:::设ans为当前的值,上一次取模的位置为p,那么我们只需要在p的右边找到一个数比ans小的第一个数,ans对那么数取模,p跳到那么位置即可。最多跳log次,每次二分一个log,复杂度就是nloglog
     
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <queue>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <map>
    #include <set>
    #include <vector>
    #include <cstdlib>
    using namespace std;
    typedef long long ll;
    const int N = 2e5 + 100;
    int n, m;
    int a[N], mm[N], mi[N][25];
    
    void initRMQ(int n, int b[]) {
            mm[0] = -1;
            for(int i = 1; i <= n; ++i) {
                mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1];
                mi[i][0] = b[i];
            }
            for(int j = 1; j <= mm[n]; ++j)
                for(int i = 1; i + (1 << j) - 1 <= n; ++i)
                mi[i][j] = min(mi[i][j - 1], mi[i + (1 << (j-1))][j - 1]);
    }
    int rmq(int x, int y) {
            if(x > y) return 0x3f3f3f3f;
            int k = mm[y - x + 1];
            return min(mi[x][k], mi[y - (1 << k) + 1][k]);
    }
    int calc(int l, int r) {
            int p = l, ans = a[l];
            while(p < r) {
                int L = 1, R = r - p + 1, tmp = R;
                while(L < R) {
                    int M = (L + R) >> 1;
                    if(rmq(p + 1, p + M) <= ans) R = M;
                    else L = M + 1;
                }
    
                if(L == tmp) return ans%a[r];
                p = p + L; //cout << p << endl;
                ans %= a[p];
            }
            return ans%a[r];
    }
    void solve() {
            scanf("%d", &n);
            for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
            int l, r;
            initRMQ(n, a);
            scanf("%d", &m);
            for(int i = 1; i <= m; ++i) {
                    scanf("%d%d", &l, &r);
                    if(l == r) printf("%d
    ", a[l]);
                    else  printf("%d
    ", calc(l, r));
            }
    }
    int main() {
    #ifdef LOCAL
        freopen("in", "r", stdin);
    #endif
        int cas;
        while(~scanf("%d", &cas)) {
            while(cas --) {
                solve();
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    理解Linux 的CPU Load和CPU利用率
    Linux进程和信号超详细分析
    Linux 磁盘配额
    linux磁盘阵列raid详解
    Linux LVM管理
    Linux fstab文件详解
    Linux 磁盘管理
    sourceTree的使用
    Logstash 参考指南(Kafka输入插件)
    ELK的一次吞吐量优化
  • 原文地址:https://www.cnblogs.com/orchidzjl/p/5861173.html
Copyright © 2011-2022 走看看