【NOIP 校内模拟】小C的序列(玄学链表)

我们固定左端点 每当右边加入一个数 那么gcd肯定在原来的基础上丢掉某几个质因数

由于一个数最多有log个质因子 所以对于一个l gcd(l,r)不同的区间最多有log个

于是我们枚举左端点 二分寻找右端点 用线段树/st表查询一个区间里的gcd 再用哈希表更新

但是只能拿80分

区间是可合并的 用链表来维护每个数的下一个不同的分界点 然后每次加 后合并相同的区间

#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define N 500005
#define ll long long
using namespace std;
using namespace tr1;
template<class T>
inline void read(T &x)
{
	x=0;
	static char ch=getchar();
	while(ch<'0'||ch>'9')	ch=getchar();
	while(ch>='0'&&ch<='9')	x=x*10+ch-'0',ch=getchar();
}
int n,q,a[N],next[N];
unordered_map<int,ll> m;
int main()
{
	read(n);	read(q);
	for(int i=1;i<=n;i++)	read(a[i]),next[i]=i+1;
	for(int i=n;i>=1;i--)
	{
		int pre=i;
		for(int j=i;j<=n;j=next[j])
		{
			a[j]=__gcd(a[j],a[pre]);
			if(a[j]==a[pre])	next[pre]=next[j];
			m[a[j]]+=(next[j]-j);
			pre=j; 
		}
	}
	while(q--)
	{
		ll x;	read(x);
		cout<<m[x]<<" ";
	}	
	return 0;
}
posted @ 2018-10-24 17:43  Patrickpwq  阅读(112)  评论(0编辑  收藏  举报