杭州区域赛的题目
题意:
给定区间[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; }