杭州区域赛的题目
题意:
给定区间[l,r] ,求[l,r]内有多少个数满足与区间内其他数都互质。
思路:
处理出每个数,最左边能互质到的位置L[i],以及右边R[i]。(具体方法看代码)
然后用树状数组维护区间的覆盖,按l离线查询。
然后从左往右扫。对于当前位置p,找出所有L[i]==p的数。然后i位置+1,R[i]+1的位置-1。因为p以及p以后的位置,这个L[i]都能覆盖到。
离开位置p的时候,要把p位置这个数的覆盖去掉。即p位置-1,R[p]+1的位置+1。
如果p位置上有查询,那么sum(r)就是答案。
总复杂度O(nlogn)
这份代码C++能AC,G++MEL。。。其实C++也要32760KB,因为用了很多vector,加上数据有20W,vector实际比存储的要大。虽然理论计算是不会MLE的。
code:
#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
#define N 200010
#define ll long long
#define ALL(x) x.begin(),x.end()
#define CLR(x,a) memset(x,a,sizeof(x))
typedef pair<int,int> PI;
const int INF=0x3fffffff;
const int MOD =1000000007;
const double EPS=1e-7;
class BIT{
private:
int sum[N],n;
public:
void init(int n){
this->n=n;
fill(sum+1,sum+n+1,0);
}
void add(int i,int x){
for(;i<=n;i+=-i&i) sum[i]+=x;
}
int get(int i){
int ans=0;
for(;i>=1;i-=-i&i) ans+=sum[i];
return ans;
}
}T;
vector<PI > Q[N];
vector<int> pos[N],prm[N];
int ans[N],l[N],r[N],idx[N],a[N];
void solve(int n,int d[]){
CLR(idx,0);
for(int i=1;i<=n;i++){
d[i]=0;
for(int j=0;j<prm[a[i]].size();j++){
d[i]=max(d[i],idx[prm[a[i]][j]]);
idx[prm[a[i]][j]]=i;
}
d[i]++;
}
}
void pretreat(int n){
solve(n,l);
reverse(a+1,a+n+1);
solve(n,r);
reverse(a+1,a+n+1);
for(int i=1,j=n;i<j;i++,j--) swap(r[i],r[j]);
for(int i=1;i<=n;i++) r[i]=n-r[i]+2;
for(int i=1;i<=n;i++) pos[l[i]].push_back(i);
}
bool vis[N];
int main(){
int n,m;
for(int i=2;i<N;i++) if(!vis[i]){
for(ll j=1ll*i*i;j<N;j+=i) vis[i]=true;
for(int j=i;j<N;j+=i) prm[j].push_back(i);
}
while(~scanf("%d%d",&n,&m),n||m){
for(int i=1;i<=n;i++){
scanf("%d",a+i);
pos[i].clear(), Q[i].clear();
}
for(int i=0;i<m;i++){
int l,r;
scanf("%d%d",&l,&r);
Q[l].push_back(make_pair(r,i));
}
pretreat(n);
T.init(n+1);
for(int i=1;i<=n;i++){
for(int j=0;j<pos[i].size();j++){
int p=pos[i][j];
T.add(p,1);
T.add(r[p],-1);
}
for(int j=0;j<Q[i].size();j++)
ans[Q[i][j].second]=T.get(Q[i][j].first);
T.add(i,-1);
T.add(r[i],1);
}
for(int i=0;i<m;i++) printf("%d\n",ans[i]);
}
return 0;
}