整除【NOIP2016提高A组模拟9.21】

来源:互联网 发布:退役特种兵知乎 编辑:程序博客网 时间:2024/06/12 19:07

题目

麦克雷有一个1~n的排列,他想知道对于一些区间,有多少对区间内的数(x,y),满足x能被y整除
样例输入:
第一行包含2个正整数n,m。表示有n个数,m个询问。
接下来一行包含n个正整数,表示麦克雷有的数列。
接下来m行每行包含2个正整数l,r。表示询问区间[l,r]。
10 9
1 2 3 4 5 6 7 8 9 10
1 10
2 9
3 8
4 7
5 6
2 2
9 10
5 10
4 10

样例输出:
共 m 行,每行一个整数,表示满足条件的对数。
27
14
8
4
2
1
2
7
9

数据范围:
30%:1<=n,m<=100
100%:1<=n,m<=2*10^5,1<=pi<=n


剖解题目

。。。。。。


思路

区间问题,经过前面的轰炸后一眼就想莫队,然而却不会打。。。


解法

对于一个合法的(x,y),必须要求其两个都在区间[l,r]里才行,只要有一个不在,就是不合法的,我们只要将全部求出来,减去不合法的就行了。
对于y,我们把询问按照第二关键字升序排列,就可以解决。
每次加进一个数,a[i],判断其因数和倍数x是否在区间[1,r]里,在就把c[pos[x]]加一,pos[i]表示i在a数组中的位置,c[i]表示i这个位置可以对答案的贡献。
求和即可。

优化
一:很明显,c这个数组可以用数据结构优化,推荐BIT,segemen tree也行。
二:求n数的因数的时间复杂度是nn级别,但求其倍数却是nlogn级别,所以我们可以避开求因数,改为正向与反向各求一遍倍数即可。
优化一必须加。优化二看时间,2s内不加也行。


代码

#include<cstdio>#include<algorithm>#include<cstdlib>#include<cmath>#define fo(i,a,b) for(int i=a;i<=b;i++)using namespace std;const int maxn=2*1e5+2;int a[maxn],tree[maxn],pos[maxn];int n,m;bool bz[maxn];struct cy{    int l,r,id,ans;}qs[maxn];bool cmp1(cy a,cy b){    return a.r<b.r;}bool cmp2(cy a,cy b){    return a.id<b.id;}int lowbit(int x){    return x&-x;}void add(int k,int x){    while (k<=n){        tree[k]+=x;        k+=lowbit(k);    }}int get(int k){    int sum=0;    while (k>0){        sum+=tree[k];        k-=lowbit(k);    }    return sum;}int main(){//  freopen("T.in","r",stdin);    scanf("%d%d",&n,&m);    fo(i,1,n) {        scanf("%d",&a[i]);        pos[a[i]]=i;    }    fo(i,1,m){        scanf("%d%d",&qs[i].l,&qs[i].r);        qs[i].id=i;    }    sort(qs+1,qs+m+1,cmp1);    fo(i,1,m){        fo(j,qs[i-1].r+1,qs[i].r){            bz[a[j]]=true;            fo(k,1,sqrt(a[j]))            if (a[j]%k==0) {                if (bz[k]) add(pos[k],1);                if (bz[a[j]/k]&&a[j]/k!=k) add(pos[a[j]/k],1);            }            add(pos[a[j]],-1);            fo(k,1,n/a[j])             if (bz[k*a[j]]) add(pos[a[j]*k],1);        }        int x=get(qs[i].r),y=get(qs[i].l-1);         qs[i].ans=x-y;    }    sort(qs+1,qs+m+1,cmp2);    fo(i,1,m) printf("%d\n",qs[i].ans);}

这里写图片描述

0 0
原创粉丝点击