zoukankan      html  css  js  c++  java
  • hdu4777 树状数组

    题意:给了n个数,然后又m次查询,询问[L,R] 内有多少个数与其他的数不互质。

    解:

       我们首先可以通过处理得出每个数的有效区间,LR 就是 左边L位置上的数 和他不互质, 右边R位置上的数和不互质,

       我们对于询问排序,R小的排前面,枚举每个R,在loc位置就将第loc个点在loc的位置加上一个1在loc的L(左不互质点)减一个1,再将枚举到该位的时候对于有在这个位置上R的点 在loc位置减1

      在loc的L位置加1

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <string.h>
    #include <vector>
    #include <cmath>
    using namespace std;
    const int maxn=200005;
    typedef long long LL;
    bool vis[maxn];
    int yinzi[maxn][10],numofYZ[maxn];
    void sieve()
    {
    
         memset(vis,false,sizeof(vis));
         memset(numofYZ,false,sizeof(numofYZ));
        for(LL i=2; i<=200000; i++)
        {
            if(vis[i])continue;
            yinzi[i][numofYZ[i]++]=i;
             for(LL j=i+i; j<=200000; j+=i)
             {
                vis[j]=true;
                yinzi[j][numofYZ[j]++]=i;
             }
        }
    }
    struct point{
       int L,R,id;
       bool operator <(const point &rhs)const {
         return R<rhs.R||( R == rhs.R && L<rhs.L);
       }
    }wLR[maxn],Q[maxn];
    int Loc[maxn];
    int w[maxn];
    vector<int>G[maxn];
    void init(int n)
    {
        for(int i=0; i<=n+1; i++)
            G[i].clear();
    }
    int n,m;
    int C[maxn];
    int lowbit(int x)
    {
        return x&(-x);
    }
    void add(int x,int v)
    {
        if(x<=0)return ;
        while(x<=n)
        {
           C[x]+=v;
           x+=lowbit(x);
        }
    }
    int sum(int x)
    {
        int ans=0;
        while(x>0)
        {
            ans+=C[x];
            x-=lowbit(x);
        }
        return ans;
    }
    int ans[maxn];
    int main()
    {
        sieve();
        while(scanf("%d%d",&n,&m)==2&&n)
        {
            int maW=0;
            for(int i=1; i<=n; i++)
                {
                    scanf("%d",&w[i]);
                   maW=max(maW,w[i]);
                }
            memset(Loc,0,sizeof(Loc));
            for(int i=1; i<=n; i++)
            {
                int ww=w[i];
                int L=0;
                for(int j=0; j<numofYZ[ ww ]; j++)
                    L=max(L,Loc[ yinzi[ ww ][ j ] ]);
                wLR[i].L=L;
                for(int j=0; j<numofYZ[ ww ]; j++)
                    Loc[ yinzi[ ww ][ j ] ] = i;
            }
            for(int i=0; i<=maW; i++)Loc[i]=n+1;
            for(int i=n; i>0; i--)
            {
                int ww=w[i];
                int R=n+1;
                for(int j=0; j<numofYZ[ ww ]; j++)
                    R=min(R,Loc[ yinzi[ ww ][ j ] ]);
                wLR[i].R=R;
                G[R].push_back(i);
                for(int j=0; j < numofYZ[ ww ]; j++)
                    Loc[ yinzi[ww][ j ] ]=i;
            }
            for(int i=0; i<m; i++)
            {
                    Q[i].id=i;
                    scanf("%d%d",&Q[i].L,&Q[i].R);
            }
            sort(Q,Q+m);
            int now=1;
            memset(C,0,sizeof(C));
            for(int i=0; i<m; i++)
            {
                while(now<=Q[i].R)
                {
                  for(int j=0; j<G[now].size(); j++)
                  {
                      int to=G[now][j];
                      add(to,-1);
                      add(wLR[to].L,1);
                  }
                  add(now,1);
                  add(wLR[now].L,-1); now++;
                }
                ans[Q[i].id]=sum(Q[i].R)-sum(Q[i].L-1);
            }
            for(int i=0; i<m; i++)
                printf("%d
    ",ans[i]);
            init(n);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Comet OJ
    LOJ#2719. 「NOI2018」冒泡排序 DP+组合+树状数组
    LuoguP6747 『MdOI R3』Teleport 二进制+贪心
    LuoguP6748 『MdOI R3』Fallen Lord 树形DP+set
    LuoguP5576 [CmdOI2019]口头禅 后缀树+线段树+暴力
    LOJ#3161. 「NOI2019」I 君的探险 整体二分+随机化+二进制分组
    LOJ#2085. 「NOI2016」循环之美 莫比乌斯反演+杜教筛
    LuoguP5327 [ZJOI2019]语言 线段树合并+树链求并
    【考试题
    ELK
  • 原文地址:https://www.cnblogs.com/Opaser/p/4934466.html
Copyright © 2011-2022 走看看