qwq
【题目分析】
考场写个大暴力结果sb的用了个multiset,结果常数大到爆炸(雾)
暴力与正解之间就隔着一个unordered_map和链表(什么鬼鬼)
关于unordered_map,详细的可以参考博客:https://blog.csdn.net/BillCYJ/article/details/78985895,如果不想看可以直接记结论:unordered_map的建立使用的是哈希表,map的建立用的是红黑树,在建立上unordered_map更耗时,但在查询上,因为使用的是哈希表,所以效率非常高。
然后扯一下正解:在一段序列上,我们将gcd相同的分割为1个区间,那么最后整个区间最多就分为了log个区间,对于每次查询,如果我们用线段树维护,每次查询二分所在区间,那么最后复杂度为O()。
考虑优化,如果我们用ST表存储,可以去掉一个查询用的logn。
我们发现,如果我们对每一个询问都去二分所在区间,其实造成了时间的很大的浪费,所以我们用链表从后往前存储分界点,然后每次加入ai,就向后进行一次区间合并,最后用unordered_map统计答案即可。
【代码~】
#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
typedef long long LL;
const int MAXN=5e5+10;
int n,q;
int a[MAXN],nxt[MAXN];
tr1::unordered_map<int,LL> ans;
int Read()
{
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
int gcd(int a,int b)
{
return a%b?gcd(b,a%b):b;
}
int main()
{
n=Read(),q=Read();
for(int i=1;i<=n;++i)
a[i]=Read();
for(int i=n;i>=1;--i)
{
int last=i;
nxt[i]=i+1;
for(int j=i;j<=n;j=nxt[j])
{
a[j]=gcd(a[j],a[last]);
if(a[j]==a[last])
nxt[last]=nxt[j];
ans[a[j]]+=(LL)(nxt[j]-j);
last=j;
}
}
while(q--)
{
int k=Read();
cout<<ans[k]<<' ';
}
return 0;
}