Function
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) (1≤l≤r≤N)
is defined as:
F(l,r)={AlF(l,r−1) 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(1≤N≤100000)
.
The second line contains
N
space-separated positive integers:
A1,…,AN (0≤Ai≤109)
.
The third line contains an integer
M
denoting the number of queries.
The following
M
lines each contain two integers
l,r (1≤l≤r≤N)
, 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
2016 ACM/ICPC Asia Regional Dalian Online
题目大意
求区间L-R中数据连续取余结果
解题思路
一个数 a%b
如果a<b 那么结果还是 a
如果a>b 那么结果会是一个新的数并且小于a小于b
所以a%b%c%d%e…… 只需要找到第一个比a小的数x,计算出a=a%x 再找第二个比a小的数………………
这里找最小的数用的是线段树维护的
线段树中存的是区间的最小值,如果这个大区间的最小值小于a,那么优先看其左儿子中的最小值是否小于a,如果左儿子最小值不小于那一定在其右儿子中。
代码
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn =0x3f3f3f3f;
int min(int a,int b)
{
return a<b?a:b;
}
struct node
{
int r,l,mmin;
}tree[400010];
int a[100000];
void buildtree(int node,int b,int e)
{
int mid =(b+e)/2;
tree[node].l=b;
tree[node].r=e;
tree[node].mmin = maxn;
if(b==e) return;
if(b<=mid)
buildtree(node*2,b,mid);
if(e>mid)
buildtree(node*2+1,mid+1,e);
}
void update(int node,int b,int e,int add)
{
if(tree[node].l>=b&&tree[node].r<=e) {tree[node].mmin=add;return;}
int mid=(tree[node].l+tree[node].r)/2;
if(b<=mid)
update(node*2,b,e,add);
if(mid<e)
update(node*2+1,b,e,add);
tree[node].mmin=min(tree[node*2].mmin,tree[node*2+1].mmin);
}
int query(int node,int ql,int qr,int x)
{
if(tree[node].l==tree[node].r)
{
if(tree[node].mmin<=x)
return tree[node].l;
else return -1;
}
int mid=(tree[node].l+tree[node].r)/2;
//先看左儿子中最小值是否小于x
if(mid>=ql && tree[node*2].mmin<=x)
{
int temp=query(node*2,ql,qr,x);
if(temp!=-1)
return temp;
//在左儿子中没找到这个最小值那一定在右儿子里面
else if(mid <qr && tree[node*2+1].mmin<=x)
return query(node*2+1,ql,qr,x);
}
//左儿子的最小值不小于x并且右儿子最小值小于x那一定在右儿子里
else if(mid<qr && tree[node*2+1].mmin<=x)
{
return query(node*2+1,ql,qr,x);
}
//左右区间都没有比x小的
return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
buildtree(1,1,n);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
update(1,i,i,a[i]);
}
int m;
scanf("%d",&m);
while(m--)
{
int ql,qr;
scanf("%d%d",&ql,&qr);
int x=a[ql];
while(ql<qr)
{
ql=query(1,ql+1,qr,x);//从下一个开始
if(ql==-1)//找不到比x更小的了(已经找到答案了)
break;
x%=a[ql];
}
printf("%d\n",x);
}
}
return 0;
}