版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/becky_w/article/details/82418513
这个题类似南京网络赛的题目
题目大意是给你一个区间[l,r] 让你求 a[l] %a[l+1]%a[l+2]%….%a[r]的值
我们发现只有取模一个小的数的时候结果才会变化,所以我们只要求 [l+1,r] 区间内第一个比当前树小的即可
用一个线段树来维护区间最小值,然后优先向左边查询
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
#define cl(a) memset(a,0,sizeof(a))
typedef long long ll;
const int maxn = 100000+50;
const int inf=0x3f3f3f3f;
int n,m,q;
int a[maxn];
struct Node
{
int l,r;
int val;
}node[4*maxn];
void pushup(int root)
{
node[root].val=min(node[root*2].val,node[root*2+1].val);
}
void build(int root,int l,int r)
{
if(l>r)return ;
node[root].l=l;
node[root].r =r;
node[root].val = 0;
if(l==r) node[root].val=a[l];
else
{
int mid = l+(r-l)/2;
build(root*2,l,mid);
build(root*2+1,mid+1,r);
pushup(root);
}
}
void update(int root,int pos,int val)
{
if(node[root].l==node[root].r)
{
node[root].val = val;
return;
}
int mid = node[root].l+(node[root].r-node[root].l)/2;
if(pos<=mid) update(root*2,pos,val);
if(pos>mid) update(root*2+1,pos,val);
pushup(root);
}
int query(int root,int st,int ed,int k)
{
int l = node[root].l;
int r = node[root].r;
int ans = 0;
if(r<l)return 0;
if(node[root].val>k)return 0;
if(st>r||ed<l)return 0;
if(node[root].l==node[root].r) return node[root].l;
if(st<=l&&ed>=r)
{
if(node[root*2].val<=k) return ans = query(root*2,st,ed,k);
if(node[root*2+1].val<=k) return ans = query(root*2+1,st,ed,k);
}
else
{
ans =query(root*2,st,ed,k);
if(!ans)
{
ans = query(root*2+1,st,ed,k);
}
return ans;
}
}
int check(int l,int r)
{
int num = a[l];
int idx = query(1,l+1,r,num);
while(idx)
{
num = num%a[idx];
idx = query(1,idx+1,r,num);
}
return num;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build(1,1,n);
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
int ans = check(l,r);
printf("%d\n",ans);
}
}
return 0;
}