HDU 4777 离线树状数组 + 思维

版权声明:存在错误或者不清楚的地方还望指出 https://blog.csdn.net/hypHuangYanPing/article/details/83033748
/**
HDU 4777 离线树状数组 + 思维
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4777

题意:区间不与其它数字互质的数的个数;

分析:可先求解互质的数的个数 再用区间长度减去即可;
维护数组l[i],r[i] : 第i个位置上的数 与左端数互质的数的最近位置 与右端数互质的数的最近位置;
Get l[i] r[i]:对当前数进行质因数分解,直接进行更新即可;

离线处理区间,用类似于莫队的思想,对所给区间按照右端点进行排序;
不断的向右进行扩展,对于当前区间,L + 1 对于枚举的 k L+1 R -1; 树状数组区间更新进行求和即可;
***************时间复杂度&&tricks*****************
nlogn 质因数的存储还是暴力的好.....

*/

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn=2e5+7;
int n,q;

struct node{
	int l,r,id;
}op[maxn];
bool cmp(node a,node b){
	return a.r<b.r;
}

int c[maxn];

int lowbit(int x){return x&(-x);}

void add(int x,int val){
	if(x==0) return ;
	while(x<=n) {
		c[x]+=val;
	    x+=lowbit(x);
	}
}

int sum(int x){
	int ans=0;
	while(x){
		ans+=c[x];
	    x-=lowbit(x);
	}
	return ans;
}

int prime[maxn],cnt=0,np[maxn];
int l[maxn],r[maxn],val[maxn];
vector<int>fac[maxn];

void getprime(){
	memset(prime,0,sizeof(prime));
	for(int i=2;i<maxn;i++){
		if(!prime[i]) prime[++cnt]=i;
		for(int j=1;j<=cnt;j++){
			if(i*prime[j]>=maxn) break;
			prime[i*prime[j]]=1;
			if(i%prime[j]==0) break;
		}
	}
	for(int i=2;i<maxn;i++){
		int x=i;
		for(int j=1;j<=cnt&&prime[j]*prime[j]<=x;j++){
			if(x%prime[j]==0) {
				while(x%prime[j]==0) x/=prime[j];
				fac[i].push_back(prime[j]);
			}
		}
		if(x>1) fac[i].push_back(x);
	}
}

vector<int>vec[maxn];
int a[maxn],tmp[maxn];

int main (){
	getprime();
	while(~scanf("%d %d",&n,&q)){
		if(n==0&&q==0) break;
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		for(int i=1;i<=q;i++) scanf("%d %d",&op[i].l,&op[i].r),op[i].id=i;
		memset(tmp,0,sizeof(tmp));
		for(int i=0;i<maxn;i++) l[i]=0;
		for(int i=1;i<=n;i++){
			int sz=fac[a[i]].size();
			for(int j=0;j<sz;j++){
				l[i]=max(l[i],tmp[fac[a[i]][j]]);
				tmp[fac[a[i]][j]]=i;
			}
		}

		for(int i=0;i<maxn;i++) tmp[i]=n+1,r[i]=n+1;
		for(int i=n;i>=1;i--){
			int sz=fac[a[i]].size();
			for(int j=0;j<sz;j++){
				r[i]=min(r[i],tmp[fac[a[i]][j]]);
				tmp[fac[a[i]][j]]=i;
			}
		}
		for(int i=0;i<=n+2;i++) vec[i].clear();
		for(int i=1;i<=n;i++) vec[r[i]].push_back(i);
		sort(op+1,op+1+q,cmp);
		memset(c,0,sizeof(c));
		for(int i=1,k=1;i<=q;i++){
			while(k<=n&&k<=op[i].r){
				add(l[k],1);
				for(int o=0;o<vec[k].size();o++){
					int v=vec[k][o];
					add(v,1);
					add(l[v],-1);
				}
				k++;
			}
			val[op[i].id]=op[i].r-op[i].l+1-(sum(op[i].r)-sum(op[i].l-1));
		}
		for(int i=1;i<=q;i++) printf("%d\n",val[i]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/hypHuangYanPing/article/details/83033748