zoukankan      html  css  js  c++  java
  • BZOJ4320 : ShangHai2006 Homework

    取$M=sqrt{300000}$。

    设$g[i]$表示程序员的$mod i$最小的值。

    若$Y<M$,那么可以在$O(M)$时间内完成对所有$g[i]$的修改,$O(1)$时间内完成查询。

    若$Ygeq M$,那么枚举$Y$的倍数,等价于查询一段区间内的最小值,可以通过分块做到$O(M)$修改,$O(1)$查询。

    因为倍数不超过$M$个,所以询问的总复杂度为$O(M)$。

    所以总时间复杂度为$O(nsqrt{300000})$。

    #include<cstdio>
    const int N=300010,M=550;
    int n=300000,m=n/M,q,i,x,pos[N],st[M],f[N],tag[M],g[M];char op[5];
    inline void up(int&a,int b){if(a>b)a=b;}
    inline void add(int x){
      for(int i=1;i<M;i++)up(g[i],x%i);
      for(int i=st[pos[x]];i<=x;i++)up(f[i],x);
      for(int i=pos[x]-1;~i;i--)up(tag[i],x);
    }
    inline int ask(int x){
      if(!x)x++;
      int t=f[x];
      up(t,tag[pos[x]]);
      return t;
    }
    inline int query(int x){
      if(x<M)return g[x];
      int t=N;
      for(int i=0,j=x;i<=n;i=j,j+=x){
        if(j>n)j=n+1;
        int y=ask(i);
        if(y<j)up(t,y-i);
      }
      return t;
    }
    int main(){
      for(i=1;i<=n;i++)pos[i]=i/M;
      for(i=n;i;i--)st[pos[i]]=i;
      for(i=1;i<=n;i++)f[i]=N;
      for(i=0;i<=m;i++)tag[i]=N;
      for(i=1;i<M;i++)g[i]=N;
      scanf("%d",&q);
      while(q--){
        scanf("%s%d",op,&x);
        if(op[0]=='A')add(x);else printf("%d
    ",query(x));
      }
      return 0;
    }
    

      

  • 相关阅读:
    开学测试感想
    动手动脑1(00JAVA语言基础)
    9.29 java web注释方式以及servlet映射
    三十道随机算法
    9.30 servlet学习
    C#验证控件的使用方法
    SqlHelper详解
    C#字符串的几种常用方法
    存储过程事务处理
    js url编码
  • 原文地址:https://www.cnblogs.com/clrs97/p/4922153.html
Copyright © 2011-2022 走看看