zoukankan      html  css  js  c++  java
  • 莫队算法

    思想:

      不修改的时间复杂度 为n*logn 修改的n*pow(n,0.6666)

       在队列里通过l,r 更新区间的答案;

       不过要分 根号n 的版块 进行(特殊)排序;

      代码:

    struct sfs{
        int l,r,pos,id; // pos 板块 
        bool operator <(const sfs b)const 
        {
            if(pos==b.pos)
            {
                if(r==b.r) return l<b.l;
                return r<b.r;
            }
            return pos<b.pos;
        }
    }p[M];
    View Code

     栗子很重要,要看

    HH 有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答,因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。
    
    输入格式
    第一行:一个整数  ,表示项链的长度。
    
    第二行: 个整数,表示依次表示项链中贝壳的编号(编号为  到  之间的整数)。
    
    第三行:一个整数  ,表示HH询问的个数。
    
    接下来  行:每行两个整数, 和 ,表示询问的区间。
    
    输出格式
     行,每行一个整数,依次表示询问对应的答案。
    
    样例
    输入样例:
    6  
    1 2 3 4 3 5  
    3  
    1 2   
    3 5  
    2 6  
    输出样例:
    2  
    2  
    4  
    数据范围与提示
    ,
     ,  。
    View Code

     代码

    //1 出现的思想
    //2 cmp 的各个的写法
    
    #include <bits/stdc++.h>
    using namespace std;
    #define ri register int
    #define M 1000005 
    
    struct sfs{
        int l,r,pos,id; // pos 板块 
        bool operator <(const sfs b)const 
        {
            if(pos==b.pos)
            {
                if(r==b.r) return l<b.l;
                return r<b.r;
            }
            return pos<b.pos;
        }
    }p[M];
    int ans[M];
    
    int col[M];
    
    int n,m;
    
    void readyy()
    {
        scanf("%d",&n);
        for(ri i=1;i<=n;i++)
        scanf("%d",&col[i]);
        
        scanf("%d",&m);
        
        int d=int(sqrt(n)+0.5); /// REMEMBER
        
        for(ri i=1;i<=m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            p[i].pos=a/d;
            p[i].l=a,p[i].r=b,p[i].id=i;
        }
        sort(p+1,p+1+m);
    }
    int num[M];int cur;
    void jia(int a)
    {
        if(!num[col[a]]) cur++;
        num[col[a]]++;    
    }
    void jian(int a)
    {
        if(num[col[a]]==1) cur--;
        num[col[a]]--;
    }
    void solv()
    {
        int l=p[1].l;
        int r=l;
        jia(r); // 起始点 // 函数此时可以正常编译 莫md 
        while(r<p[1].r)
        {
            jia(++r);
        }
        ans[p[1].id]=cur;
    //    printf("%d\n",r); 
        for(ri i=2;i<=m;i++) // 是从第二个开始 
        {
            // 下面写法 可以 就是让 l,r到达想要的地方。 
            while(l<p[i].l) jian(l++); // 到达那个的点不用减去,起始的点要减去;以下同理可得 
            while(l>p[i].l) jia(--l);
            while(r<p[i].r) jia(++r);
            while(r>p[i].r) jian(r--);
            ans[p[i].id]=cur;  
        }
        
        for(ri i=1;i<=m;i++)
        printf("%d\n",ans[i]);
        
    }
    int main(){
        
        readyy();
        solv();
        return 0; 
        
    }
    
      
    View Code

     修改莫队

     

    struct dian{
        int l,r,pos,id,tim;
        bool operator <(const dian &t)const 
        {
            if(pos==t.pos) 
              {
                  if(r/d==t.r/d) return tim<t.tim;
                  return r<t.r;
              }
              return l<t.l;
        }
    }p[M];
    void work (int v,int k)
    {  
        vis[cent[v]]--;
        cent[v]+=k;
        vis[cent[v]]++;
    }
    void work_tim(int ti,int i)
    {
        if(p[i].l<=gai[ti].mubiao&&gai[ti].mubiao<=p[i].r)
            {
                work(val[gai[ti].mubiao],-1);
                work(gai[ti].VAL,1);
            }
            swap(val[gai[ti].mubiao],gai[ti].VAL);
    }
    d=pow(n,0.6666);
        for(ri i=1;i<=m;i++)
        {   int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            if(a==1)
            {
                p[++trmp].l=b;
                p[trmp].r=c;
                p[trmp].id=trmp;p[trmp].tim=sj;
                p[trmp].pos=p[trmp].l/d;
            }
            else
            {
              gai[++sj].mubiao=b;
              tt[n+sj]=gai[sj].VAL=c;    
            }
        }
        sort(p+1,p+trmp+1);
        sj=0;
        for(ri i=p[1].l;i<=p[1].r;i++)
        {    
             work(val[i],1);      
        }
        int baba;
        while(sj<p[1].tim) work_tim(++sj,1);
        while(sj>p[1].tim) work_tim(sj--,1);  // li hai
        for (ANS[p[1].id]=1;vis[ANS[p[1].id]]>0;ANS[p[1].id]++);
        for(ri i=2;i<=m;i++)
        {
            int l=p[i-1].l;
            int r=p[i-1].r;
            
            while(l<p[i].l) work(val[l++],-1);
            while(r>p[i].r) work(val[r--],-1);
            while(l>p[i].l) work(val[--l],1);
            while(r<p[i].r) work(val[++r],1);
            while(sj<p[i].tim) work_tim(++sj,i);
             while(sj>p[i].tim) work_tim(sj--,i);  
            //跟新ans 
            } 
    View Code

     注意 d的取值为什么有时取 pow(n,0.6666)呢 而不是 int(0.5+sqrt(n))

  • 相关阅读:
    【转】机器学习算法一览,应用建议与解决思路
    机器学习笔记04(Logistic Regression)
    机器学习笔记03(Classification: Probabilistic Generative Model)
    机器学习笔记00(课程结构)
    .Net PE
    wpf 画五角星函数
    .Net Core CLR FileFormat Call Method( Include MetaData, Stream, #~)
    天子守国门,君王死社稷
    CoreCLR Host源码分析(C++)
    Core CLR Host 源码简单分析
  • 原文地址:https://www.cnblogs.com/Lamboofhome/p/11709877.html
Copyright © 2011-2022 走看看