给n个数,m个询问, 问任意区间内与其它数互质的数有多少个

比如3个数1 2 4,询问[1,3] 那么答案是1

千万要记住,这样的题目,如果你不转变下,使劲往线段树想(虽然转变之后,也说要用到线段树,但是维护的东西不同了),那么会发现这样的题目,区间与区间之间是无法传递信息的,

区间与区间是无法传递信息的,区间与区间之间是无法传递信息的,重要的东西说三遍。

设n个数,存在数组a[]里面

我们预处理出,L[],和R[],L[i] 表示从i往左,第一个与a[i]不互质的数的位置+1,  R[i]表示从i往右,第一个与a[i]不互质的数的位置-1

即L[i] 表示 [L[i],i]内的所有数都与a[i]互质,R[i]表示[i,R[i]]内的所有数都与a[i]互质

然后我们离线处理,将所有的询问按照左端点排序

然后枚举左端点i,将所有L[j] = i的 [j,R[j]]区间+1,因为当左端点为i时,L[j]=i的数都在各自的有效区间[j,R[j]]里面生效了

当i=询问的区间的左端点时,只要查询右端点被加了多少次就行了。

走过i时,第i个数不再生效,所以将[i,R[i]]区间-1

 #include<cstdio>
 #include<iostream>
 #include<string.h>
 #include<algorithm>
 #include <vector>
 using namespace std;
  + ;
 vector<int> prime[N];
 vector<int> cL[N];
 int a[N],L[N],R[N];
 int mark[N];
 ],lazy[N<<];
 int ans[N];
 void pushDown(int rt)
 {
     if(lazy[rt])
     {
        lazy[rt<<] += lazy[rt];
        lazy[rt<<|] += lazy[rt];
        tree[rt<<] += lazy[rt];
        tree[rt<<|] += lazy[rt];
        lazy[rt] = ;
     }
 }
 void update(int l, int r, int rt, int L, int R, int val)
 {
     if(L<=l && R>=r)
     {
         lazy[rt]+=val;
         tree[rt] += val;
         return;
     }
     pushDown(rt);
     ;
     if(L<=mid)
         update(l,mid,rt<<,L,R,val);
     if(R>mid)
         update(mid+,r,rt<<|,L,R,val);

 }
 int  query(int l, int r, int rt, int pos)
 {
     if(l==r)
     {
         return tree[rt];
     }
     pushDown(rt);
     ;
     if(pos<=mid)
         ,pos);
     else
         ,r,rt<<|,pos);
 }
 struct Node
 {
     int l,r,id;
     bool operator<(const Node&rhs)const
     {
         return l < rhs.l;
     }
 }q[N];

 void getPrime()
 {
     ;i<=;++i)
     {
         if(!mark[i])
         ;j+=i)
         {
             mark[j] = true;
             prime[j].push_back(i);//得到j的所有素数因子i
         }
     }
 }
 void init(int n)
 {
     memset(mark,,sizeof(mark));
     ; i<prime[a[]].size(); ++i)
         mark[prime[a[]][i]] = ;
     L[] = ;
     cL[].push_back();
     ;i<=n;++i)
     {
         ;
         ; j<prime[a[i]].size(); ++j)
         {
             pos = max(pos,mark[prime[a[i]][j]]);
             mark[prime[a[i]][j]] = i;
         }
         L[i] = pos + ;
         cL[L[i]].push_back(i);
     }
     ;i<N;++i)mark[i] = n + ;
     ;i<prime[a[n]].size(); ++i)
         mark[prime[a[n]][i]] = n;
     R[n] = n;
     ;i>=;--i)
     {
         ;
         ;j<prime[a[i]].size(); ++j)
         {
              pos = min(pos,mark[prime[a[i]][j]]);
              mark[prime[a[i]][j]] = i;
         }
         R[i] = pos - ;
     }
 }
 int main()
 {
     int n,m;
     getPrime();
     while(scanf("%d%d",&n,&m),n+m)
     {
         memset(tree,,sizeof(tree));
         memset(lazy,,sizeof(lazy));
         ;i<=n;++i)
         {
             scanf("%d",&a[i]);
             cL[i].clear();
         }
         init(n);
         ;i<m;++i)
         {
             scanf("%d%d",&q[i].l,&q[i].r);
             q[i].id = i;
         }
         sort(q,q+m);
         ;
         //枚举左端点
         ;i<=n;++i)
         {
             //当左端点为i时,使得所有L[j] = i的数都在各自的区间[j,R[j]]
             //所以在[j,R[j]]区间+1
             ;j<cL[i].size(); ++j)
                 update(,n,,cL[i][j],R[cL[i][j]],);
             //当询问的左端点为i时,
             while(q[cur].l==i)
             {
                 //只要询问右端点的值就行了,因为每个数都在自己能生效的区间里面+1了
                 ans[q[cur].id] = query(,n,,q[cur].r);
                 cur++;
             }
             //要走过第i个数了,所以第i个数不再生效了,所以将[i,R[i]]区间-1
             update(,n,,i,R[i],-);
         }
         ;i<m;++i)
             printf("%d\n",ans[i]);
     }
     ;
 }

hdu(预处理+线段树)的更多相关文章

  1. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  2. hdu 3974 线段树 将树弄到区间上

    Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  3. hdu 3436 线段树 一顿操作

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  4. hdu 3397 线段树双标记

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  5. hdu 4578 线段树(标记处理)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others) ...

  6. hdu 4533 线段树(问题转化+)

    威威猫系列故事——晒被子 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

  7. hdu 2871 线段树(各种操作)

    Memory Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  8. hdu 4052 线段树扫描线、奇特处理

    Adding New Machine Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  9. hdu 1542 线段树扫描(面积)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

随机推荐

  1. ASP.NET Core 中文文档 第二章 指南(4.9)添加验证

    原文:Adding Validation 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘).娄宇(Lyrics).许登洋(Seay) 在本章节中你将为 Movie 模型 ...

  2. BNUOJ-26586 Simon the Spider 最小生成树+枚举

    题目链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=26586 题意:给一个图,每条边有一个权值.要你求选择一棵树,权值和为sum,然后在树上选择 ...

  3. PYTHON之批量文件指定字符串替换

    在工作应用中,运维自动化的基础是标准化. 而标准化的工作,是难点,在公司相关部门的配合. 那么,在有标准化之后,相应的部署脚本,就比较好写了. 贡献一个在类似环境下可以运用的东东.. 当然,可以写得更 ...

  4. PHP开发Android应用程序(转)

    第一部分是指在Android系统的手机上直接写PHP脚本代码并立即运行:第二部分则继续讲解如何把写好的PHP脚本代码打包成akp安装文件. 首先,在手机上安装两个apk包. 一个是SL4A(Scrip ...

  5. hdu 4963(中途相遇法)

    题目链接:Dividing a String 题意:给定一个2*n(n<=20)的字符串及每个位置的字符包含的权重,求将该字符串分成两个子序列S1.T1,要求S1=T1且abs(weight1- ...

  6. Log4j使用详解

    1 Log4j配置说明 1.1 配置文件Log4j可以通过java程序动态设置,该方式明显缺点是:如果需要修改日志输出级别等信息,则必须修改java文件,然后重新编译,很是麻烦: log4j也可以通过 ...

  7. CopyOnWriteArrayList你都不知道,怎么拿offer?

    前言 只有光头才能变强 前一阵子写过一篇COW(Copy On Write)文章,结果阅读量很低啊...COW奶牛!Copy On Write机制了解一下 可能大家对这个技术比较陌生吧,但这项技术是挺 ...

  8. Java Web之EL

    <%-- Created by IntelliJ IDEA. User: Vae Date: 2019/1/2 Time: 12:19 To change this template use F ...

  9. Linux文件权限属性后面有个点

    坑啊,新上的机器,监控怎么都不好使,各种报错说:没有权限 什么情况? 仔细查看,发现文件权限属性后面怎么多了个点,类似如下: 这是什么? 原来: 开启了SELinux功能的Linux系统就会有这个点. ...

  10. DTLS协议中client/server的认证过程和密钥协商过程

    我的总结:DTLS的握手就是协商出一个对称加密的秘钥(每个客户端的秘钥都会不一样),之后的通信就要这个秘钥进行加密通信.协商的过程要么使用非对称加密算法进行签名校验身份,要么通过客户端和服务器各自存对 ...