Function
Time Limit: 7000/3500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3915 Accepted Submission(s): 1250
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
题意:
问L位置的数模L+1,L+2....R的结果是多少
思路:
数模比它大的数是没有意义的,所以只要每次找它后面到R的区间比它小的数,取模后再找比结果更小的数
可以用线段树来查找,预处理的算法最坏情况下是N^2应该是过不了,说明数据比较水 -。-
更正:想错了,不是n^2的复杂度,取模之后数会减小一半,所以最多是log1e9
线段树:
#include <bits/stdc++.h>
using namespace std;
struct node
{
int l,r;
int id;
int w;
};
struct node tree[400100];
int n,cnt,m;
int num[100100];
void built(int i,int l,int r)
{
tree[i].l=l;
tree[i].r=r;
if(l==r)
{
tree[i].w=num[++cnt];
tree[i].id=cnt;
return;
}
int mid=(l+r)>>1;
built(i<<1,l,mid);
built(i<<1|1,mid+1,r);
tree[i].w=min(tree[i<<1].w,tree[i<<1|1].w);
}
void query(int i,int l,int r,int v,int &pos)
{
if(tree[i].w>v)
return;
if(tree[i].l>r||tree[i].r<l)
return;
int mid=(tree[i].l+tree[i].r)>>1;
if(tree[i].l==tree[i].r)
{
pos=tree[i].id;
return;
}
int tmp=pos;
query(i<<1,l,r,v,pos);
if(pos!=tmp)
return;
query(i<<1|1,l,r,v,pos);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
cnt=0;
built(1,1,n);
scanf("%d",&m);
int x,y;
while(m--)
{
scanf("%d%d",&x,&y);
int ans=num[x];
int pos=x;
while(pos+1<=y)
{
int tmp=pos;
query(1,pos+1,y,ans,pos);
if(tmp==pos)
break;
ans%=num[pos];
}
printf("%d\n",ans);
}
}
}
预处理:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
int n,m;
int num[100010];
int to[100010];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(to,-1,sizeof to);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(num[j]<=num[i])
{
to[i]=j;
break;
}
}
if(to[i]==-1)
to[i]=n;
}
to[n]=n+1;
scanf("%d",&m);
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
int ans=num[x];
x=to[x];
while(x<=y)
{
ans%=num[x];
x=to[x];
}
printf("%d\n",ans);
}
}
}