hdu 4630 No Pain No Game(树状数组离线操作)

来源:互联网 发布:国外网络流行模式 编辑:程序博客网 时间:2024/05/29 14:29

题目大意:

      给你n个数分别为a1,a2,a3,a4,a5,a6,a7.......an。

      询问 l.r 问区间[l.r]内的任意两个数的最大公约数是多少?

解决方法:

       首先对查询区间按照左端点从大到小的顺序排序。

       建立一个pre[i]数组记录,约数i上一次出现的位置,pre[i]初始值为-1。

       建立一个树状数组,树状数组维护的是区间最大值。

       然后依此对an,a(n-1),....a2,a1,进行处理,对于每个数求出其所有的约数,并且针对每个约数i,对树状数组进行修改,修改与区间和修改类似,但是将求和改为tree[i]=max(tree[i],v);

       查询:当处理到第j个是时就要将左区间为j的所有查询都处理完毕,如果其右区间为r,结果就是树状数组前r项的最大值,用树状数组很容易就可以求出来。

我的代码:

#include <cstdio>#include <algorithm>#include <iostream>#include <cstring>#include <cmath>#define maxn 50010using namespace std;struct Point {  int x,y,id,ans;}po[maxn];int pre[maxn];int tree[maxn];int num[maxn];int n,m;bool cmp(Point x, Point y){  return x.x<y.x;}bool cmp1(Point x,Point y){  return x.id<y.id;}int add(int x,int v){  //cout<<v<<endl;  for (int i=x;i<=n;i+=i&(-i))     tree[i]=max(tree[i],v);  return 0;}int maxx(int x){  int _max=-1;  for (int i=x;i>0;i-=i&(-i))    _max=max(_max,tree[i]);  return _max;}int change(int n){  int k=(int)sqrt(num[n]);  //cout<<"num   "<<num[n]<<endl;  //cout<<"k     "<<k<<endl;  for (int i=1;i<=k;i++){     if (num[n]%i==0){        //cout<<" i  "<<i<<endl;        //cout<<" i  "<<num[n]/i<<endl;        if (i==k){            if (k*k==num[n]){              //cout<<"III"<<endl;              if (pre[i]){                add(pre[i],i);                pre[i]=n;             }             else pre[i]=n;            }            else {               if (pre[i]){                add(pre[i],i);                pre[i]=n;               }               else pre[i]=n;               if (pre[num[n]/i]){                add(pre[num[n]/i],num[n]/i);                pre[num[n]/i]=n;               }               else pre[num[n]/i]=n;            }        }        else {           if (pre[i]){              add(pre[i],i);              pre[i]=n;           }           else pre[i]=n;           if (pre[num[n]/i]){              add(pre[num[n]/i],num[n]/i);              pre[num[n]/i]=n;           }           else pre[num[n]/i]=n;        }     }  }  return 0;}int main (){  //freopen("test.in","r",stdin);  int T;scanf("%d",&T);  while (T--){    memset(tree,0,sizeof(tree));    memset(pre,0,sizeof(pre));    scanf("%d",&n);    for (int i=1;i<=n;i++) scanf("%d",&num[i]);    scanf("%d",&m);    for (int i=1;i<=m;i++) scanf("%d%d",&po[i].x,&po[i].y),po[i].id=i;    sort(po+1,po+m+1,cmp);    int pos=n;    for (int i=m;i>=1;i--){        while (po[i].x<=pos){            change(pos--);        }        if (po[i].x==po[i].y) po[i].ans=0;        else po[i].ans=maxx(po[i].y);    }    sort(po+1,po+m+1,cmp1);    for (int i=1;i<=m;i++)      printf("%d\n",po[i].ans);  }  return 0;}



0 0
原创粉丝点击