Function
Time Limit: 7000/3500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 744 Accepted Submission(s): 284
Total Submission(s): 744 Accepted Submission(s): 284
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) .
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.
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
赛事上大家大部分都是通过取固定点的右端的第一个比本身小的数,跳着取值mod水过去的。
其实也有一定道理,也可以学一下其中原理,估计有什么题用得上也不一定。
当然,个人还是比较倾向题解写的解法。q个查询一起做,很容易想到同一个数最多取logn次mod(每次mod至少折半);
q个查询,用set维护一下,时间复杂度n*logn*logn;
当然,其中用set的时候总wa,后来发现即使是结构体,set也是默认的排序里的元素为key值,依旧不能存储相同值,即使还有其他元素不一样。
然后默默的改成multiset才ac,还是太水了。。。
题意:给出 a1,a2,…,ana_1, a_2, \ldots, a_na1,a2,…,an
和 qqq
个询问 [i,j][i, j][i,j]
表示询问 aimodai+1mod…modaja_{i} mod a_{i + 1} mod \ldots mod a_{j}aimodai+1mod…modaj
的值。
题解:
如果 a≥ba \geq ba≥b
,那么 amodb≤a2a mod b \leq \frac{a}{2}amodb≤2a
.
所以,如果使用线段树每次找到下一个不超过当前余数的数。因为每次余数减少至少一半,复杂度应该是 O(qlognlogAi)O(q \log n \log A_i)O(qlognlogAi)
.
实际上,上述做法会因为常数原因 TLE.
一个容易实现的方法是:把 q 个询问一起进行。我们可以拿 std::set 按照当前余数大小从大到小排序,每次比 a[i] 大的肯定是 std::set 中最大的若干元素,暴力修改它们即可。
赛事上大家大部分都是通过取固定点的右端的第一个比本身小的数,跳着取值mod水过去的。
其实也有一定道理,也可以学一下其中原理,估计有什么题用得上也不一定。
当然,个人还是比较倾向题解写的解法。q个查询一起做,很容易想到同一个数最多取logn次mod(每次mod至少折半);
q个查询,用set维护一下,时间复杂度n*logn*logn;
当然,其中用set的时候总wa,后来发现即使是结构体,set也是默认的排序里的元素为key值,依旧不能存储相同值,即使还有其他元素不一样。
然后默默的改成multiset才ac,还是太水了。。。
#include<bits/stdc++.h>
using namespace std;
const int maxn=100100;
struct Node
{
int id,w,r;
bool operator<(const Node&p)const
{
return w>p.w;
}
};
struct edge
{
int l,r,id;
bool operator<(const edge&p)const
{
return l<p.l;
}
}A[maxn];
multiset<Node>s;
multiset<Node>::iterator it;
int num[maxn],ans[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
}
int q;
scanf("%d",&q);
for(int i=0;i<q;i++)
{
scanf("%d%d",&A[i].l,&A[i].r);
A[i].id=i;
}
sort(A,A+q);
int len=0;
s.clear();
for(int i=1;i<=n;i++)
{
for(it=s.begin();(it->w)>=num[i]&&it!=s.end();)
{
Node cc=*it;
if(cc.r<i)
{
ans[cc.id]=cc.w;
s.erase(it++);
continue;
}
s.erase(it++);
cc.w%=num[i];
s.insert(cc);
}
while(A[len].l==i)
{
Node cc;
cc.id=A[len].id;
cc.w=num[i];
cc.r=A[len].r;
s.insert(cc);
len++;
}
}
for(it=s.begin();it!=s.end();it++)
ans[it->id]=it->w;
for(int i=0;i<q;i++)
printf("%d\n",ans[i]);
}
return 0;
}