2016 大连网赛---Function(单调栈)

题目链接

http://acm.split.hdu.edu.cn/showproblem.php?pid=5875

 

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
 
Source
 
Recommend
wange2014   |   We have carefully selected several similar problems for you:   5877  5876  5874  5873  5872 
 
题意:一个长度为n的数列,q次询问,每次输入l 和 r 表示一个区间A[l]~A[r]  求A[l]%A[l+1]A[l+2]...A[r];
 
思路:a%b=r  那么r<a 所以在区间连续取余中 如果一个数对A[i]取完余,后面的数大于A[i],则不用取余,所以只需要找A[i]后小于A[i]且最近的A[j]进行取余,依次进行下去。其实找距离最近且小于自己的数就是 单调栈,这个算法很神奇,复杂度为O(n);
 
代码如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
using namespace std;
int A[100005];
int pos[100005];
int s[100005];

int main()
{
    int T,N,M;
    cin>>T;
    while(T--)
    {
        scanf("%d",&N);
        for(int i=1;i<=N;i++)
            scanf("%d",&A[i]);
        int num=1;
        A[N+1]=-1;
        s[1]=N+1;
        for(int i=N;i>=1;i--)///单调栈;
        {
            while(A[i]<A[s[num]]) num--;
            pos[i]=s[num];
            s[++num]=i;
        }
        scanf("%d",&M);
        while(M--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            int tmp=A[l];
            while(l<=r)
            {
                if(tmp==0) break;
                if(pos[l]>r) break;
                tmp=tmp%A[pos[l]];
                l=pos[l];
            }
            printf("%d\n",tmp);
        }
    }
    return 0;
}

 

 
 

转载于:https://www.cnblogs.com/chen9510/p/5862834.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值