hdu4777 求区间内与其它数均互质的数的个数(树状数组+离线处理)
2014-05-07 02:28
459 查看
hdu4777 求区间内与其它数均互质的数的个数
题意:有n(1<=n<=200000)个数字,m(1<=m<=200000)个查询,每次询问[l,r]区间这些数字中,和区间内其他数都互质的数有多少个。
解题思路:
离线处理+树状数组,首先预处理出[1,200000]所有数的质因子,放到have[]里面,然后根据输入的n个数w[],求出每个数的它的质因子
出现的最左位置以及最右位置。然后对m个查询离线,按右边由小到大排序。如第二个样例:
3 6 1 2 5 3
l[] 0 1 0 2 0 2
r[] 2 4 7 7 7 7
V[] {} {1} {} {2} {3,4,5,6}
明显,求[left,right]区间的结果是(right-left+1-notFit),其中notFit=i的数量(l[i]>=left)+i的数量(r[i]<=right)-i的数量(l[i]>=left && r[i]<=right) ;
可以从左往右扫描,对于第i个,先add(l[i],1),因为左边的notFit数目多了1(自己),然后对V[i]集合里的数x=V[i][j],先add(x,1);因为
x的右边已经超出范围了,所以变为notFit,另外要add(l[x],-1);意思是减去右边notFit的并且左边也notFit的,所以结果就是
sum( right-left+1-( sum(right)-sum(left-1) ) )
参考资料:/article/2719818.html
题意:有n(1<=n<=200000)个数字,m(1<=m<=200000)个查询,每次询问[l,r]区间这些数字中,和区间内其他数都互质的数有多少个。
解题思路:
离线处理+树状数组,首先预处理出[1,200000]所有数的质因子,放到have[]里面,然后根据输入的n个数w[],求出每个数的它的质因子
出现的最左位置以及最右位置。然后对m个查询离线,按右边由小到大排序。如第二个样例:
3 6 1 2 5 3
l[] 0 1 0 2 0 2
r[] 2 4 7 7 7 7
V[] {} {1} {} {2} {3,4,5,6}
明显,求[left,right]区间的结果是(right-left+1-notFit),其中notFit=i的数量(l[i]>=left)+i的数量(r[i]<=right)-i的数量(l[i]>=left && r[i]<=right) ;
可以从左往右扫描,对于第i个,先add(l[i],1),因为左边的notFit数目多了1(自己),然后对V[i]集合里的数x=V[i][j],先add(x,1);因为
x的右边已经超出范围了,所以变为notFit,另外要add(l[x],-1);意思是减去右边notFit的并且左边也notFit的,所以结果就是
sum( right-left+1-( sum(right)-sum(left-1) ) )
参考资料:/article/2719818.html
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<iostream> #include<algorithm> #include<queue> #include<stack> #include<vector> #include<map> #include<set> #include<deque> #include<bitset> #define N 201005 using namespace std; int w ,l ,r ;//l[i],r[i]保存第i个数的质因子出现的最左位置以及最右位置 vector<int>V ;//V[i]存储的是j,其中r[j]=i vector<int>have ,VPrime;//have[i]存储的是数字i分解的质因子,VPrime存储的是[1,200000]的素数 int ans ;//存储结果 int flag ; struct node { int left,right,id; }p ; int cmp(node aa,node bb) { return aa.right<bb.right; } int ar ; int lowb(int t) { return t&(-t); } void add(int i,int v) { if(i==0) return; for(;i<N;ar[i]+=v,i+=lowb(i)); } int sum(int i) { int s=0; for(;i>0;s+=ar[i],i-=lowb(i)); return s; } void getHave(int index,int v) { int i=0; while(v>1&&i<VPrime.size()) { if(VPrime[i]*VPrime[i]>v) { have[index].push_back(v); break; } if(i<VPrime.size()&& v%VPrime[i]==0) { have[index].push_back(VPrime[i]); } while(i<VPrime.size()&& v%VPrime[i]==0) { v/=VPrime[i]; } i++; } } bool prime ; void init() { int i,j; memset(prime,0,sizeof(prime)); prime[1]=prime[0]=1; for(i=2;i<=N-2;i++) for(j=2;i*j<=N-2;j++) { prime[i*j]=1; } VPrime.clear(); for(i=2;i<=N-2;i++) { if(prime[i]==0) VPrime.push_back(i); } for(i=0;i<N;i++) { have[i].clear(); } for(i=2;i<N;i++) { getHave(i,i); } } void init2(int n)//计算出l数组,r数组以及V[] { for(int i=0;i<=n;i++) { V[i].clear(); } memset(l,0,sizeof(l)); memset(r,0,sizeof(r)); memset(flag,0,sizeof(flag)); for(int i=1;i<=n;i++) { int left=0; for(int j=0;j<have[w[i]].size();j++) { left=max(left,flag[have[w[i]][j]]); } l[i]=left; for(int j=0;j<have[w[i]].size();j++) { flag[have[w[i]][j]]=i; } } for(int i=1;i<N;i++)//这里要初始化为n+1 {flag[i]=n+1;} for(int i=n;i>=1;i--) { int right=n+1; for(int j=0;j<have[w[i]].size();j++) { right=min(right,flag[have[w[i]][j]]); } r[i]=right; for(int j=0;j<have[w[i]].size();j++) { flag[have[w[i]][j]]=i; } } for(int i=1;i<=n;i++) { V[r[i]].push_back(i); } } int main() { int i,j,k; int n,m,t; init(); while(scanf("%d%d",&n,&m)!=EOF&&!(n==0&&m==0)) { for(i=1;i<=n;i++) { scanf("%d",&w[i]); } init2(n); for(i=1;i<=m;i++) { scanf("%d%d",&p[i].left,&p[i].right); p[i].id=i; } sort(p+1,p+1+m,cmp); memset(ar,0,sizeof(ar)); i=1; for(j=1;j<=m;j++) { while(i<=p[j].right) { add(l[i],1);//将左边notFit的+1 for(k=0;k<V[i].size();k++) { add(l[V[i][k]],-1);//将左边跟右边同时notFit的-1,去掉重复 add(V[i][k],1);//将右边notFit的+1 } i++; } int notFit=sum(p[j].right)-sum(p[j].left-1); ans[p[j].id]=p[j].right-p[j].left+1-notFit; } for(i=1;i<=m;i++) { printf("%d\n",ans[i]); } } } /* input: 3 2 2 1 4 1 2 1 3 6 4 3 6 1 2 5 3 1 3 4 6 4 4 2 6 0 0 output: 2 1 1 3 1 2 */
相关文章推荐
- Hdu4417线段树求区间统计+离线处理 线段树 树状数组
- BZOJ-1901 Zju2112 Dynamic Rankings 函数式线段树 套 树状数组+离线处理
- CF A. Greg and Array (区间离线处理)
- 离线处理(线段树|树状数组)| 莫对算法 —— HDU 4638 Group
- HDU 3874 离线处理,树状数组
- 1878: [SDOI2009]HH的项链 (树状数组+离散化+离线处理)
- BZOJ 3110 [Zjoi2013]K大数查询 (整体二分 + 树状数组或线段树处理区间合值)
- BZOJ-1901 Zju2112 Dynamic Rankings 函数式线段树 套 树状数组+离线处理
- HDU 3333 Turing Tree --树状数组+离线处理
- fzu count 求区间之间x的个数 离线+树状数组
- SPOJ3267 D-Query 树状数组离线操作 或 主席树 查询某一区间内有多少不同的数
- 51Nod1463 找朋友(离线处理+树状数组维护区间最大值)
- SPOJ DQUERY(树状数组离线处理 or 主席树 区间不同数个数)
- HDU-4331 Image Recognition 关系转换+离线处理+树状数组
- HDU 4417 Super Mario (树状数组+离线处理)(划分树+二分答案)
- hdu 4417 Super Mario(树状数组+离线处理)
- HDU 3333 Turing Tree(树状数组+离线处理+离散化)
- [CF#365 (Div. 2) Mishka and Interesting sum] 线段树离线处理区间不同数
- HDU 4638 Group (2013多校4 1007 离线处理+树状数组)
- hdu4630(树状数组+离线处理)