hdu 5381 The sum of gcd

http://acm.hdu.edu.cn/showproblem.php?pid=5381

一条莫队算法的题。本来也有过这样的考虑,然而因为并不能O(1)得到区间转移的值,所以一开始放弃了。想不到题目数据比较小,卡过去了。。。。

莫队算法本质上就是把原来的查询顺序改变。

先把整个区间分块,每块长度为sqrt(n);

对于左端点在同一区间的询问,我们对他们的右端点排序;

为了叙述方便,我们记一个查询左边界为l,右边界为r;其左端点在第k块,每块长度为len;

查询的时候,分为四部分记录:左端点这一块的gcd和,i到(k+1)*len-1的gcd值(i属于[l,(k+1)*len-1]);

(k+1)*len 到r部分的所有gcd和,(k+1)*len到j的所有gcd值 (j属于[(k+1)*len,r]);(当r<(k+1)*len时特判)

注意到后两部分的求解可以在前一次的计算上叠加,这就是节省时间的来源了

#include   
#include   
#include   
#include   
#include   
using namespace std;  

#define maxn 10005  
#define ll unsigned long long  

ll gcd (ll a,ll b) {
	if(b>a) return gcd(b,a);
	return b==0?a:gcd(b,a%b);
}

int block;

struct node {
	int l,r,id;
	bool operator < (const node& an) const {
		if(l/block==an.l/block) return r lvec,ltrvec,rvec,rtlvec;

ll a[maxn],ans[maxn];

int main () 
{
	freopen("aa.txt","r",stdin);
	int T,n,q,i,j,k,p,f;
	cin>>T;
	while(T--) {
		cin>>n;block=(int)sqrt((double)n);
		for(i=1;i<=n;i++) scanf("%I64u",&a[i]);
		cin>>q;
		for(i=1;i<=q;i++) {
			scanf("%d%d",&query[i].l,&query[i].r);
			query[i].id=i;
		}
		sort(query+1,query+1+q);
		int nb=-1,rr;ll res;

		for(i=1;i<=q;i++) {
			if(query[i].l/block!=nb) {
				nb=query[i].l/block;res=0;
				rvec.clear();rtlvec.clear();
				rr=(nb+1)*block;
			}
			while(rr<=query[i].r) {
				for(j=0;jj) rvec.pop_back();
				if(rtlvec.empty()) {
					rtlvec.push_back(hav(a[rr],1));
				}
				else {
					k=rtlvec.size()-1;
					ll val=gcd(a[rr],rtlvec[k].g_val);
					if(val==rtlvec[k].g_val) rtlvec[k].num++;
					else rtlvec.push_back(hav(val,1));
				}
				rr++;
			}

			lvec.clear();ltrvec.clear();p=query[i].id;ans[p]=0;
			if(query[i].r<(nb+1)*block) {
	//			cout<<"id:"<k) lvec.pop_back();
				}
			}
			else {
				for(j=(nb+1)*block-1;j>=query[i].l;j--) {
					for(k=0;kk) lvec.pop_back();

					if(ltrvec.empty()) ltrvec.push_back(hav(a[j],1));
					else {
						k=ltrvec.size()-1;
						ll val=gcd(a[j],ltrvec[k].g_val);
						if(val==ltrvec[k].g_val) ltrvec[k].num++;
						else ltrvec.push_back(hav(val,1));
					}
				}
				ans[p]+=res;
				for(j=0;j


你可能感兴趣的:(离线算法,离线算法,莫队算法)