codeforces 301D Yaroslav and Divisors

题目大意:

     给你n个数,然后问你区间内有几对数a,b(b%a=0)。

解决方法:

    将所有的区间都进行排序(按照左端点的大小),建立一个pre【i】数组,它表示i上一次出现在某个位置,pre【i】初始值为0.

    从右向左处理每个数字,将每个数字的因子与倍数k都求出来,然后树状数组进行add(pre[k],1)的操作。某段区间的答案就是sum(右端点)。

    为什么呢?想想如果k是i的因子或者倍数,i在pos1处,k在pos2处,那么所有区间包含pos1与pos2的都要加上1,我们又是左端点排序,所有直接求sum(右端点)就行了。

我的代码:

#include 
#include 
#include 
#include 
#include 
#define maxn 1000000
using namespace std;
int pre[maxn];
long long tree[maxn];
struct Point {
  int x,y,id;
  long long ans;
}po[maxn];
int num[maxn];
int n,m;
int maxx;
int add(int x,long long v){
  for (int i=x;i<=n;i+=i&(-i))
      tree[i]+=v;
  return 0;
}
long long sum(int x){
  long long ans=0;
  for (int i=x;i>0;i-=i&(-i))
     ans+=tree[i];
  return ans;
}
int cmp(Point a,Point b){
  return a.y1)po[i].ans=sum(po[i].y)-sum(po[i].x-1);
        else po[i].ans=sum(po[i].y);
    }
    sort(po+1,po+m+1,cmp1);
    for (int i=1;i<=m;i++)
        printf("%I64d\n",po[i].ans);
  }
  return 0;
}


你可能感兴趣的:(数据结构-----树状数组)