zoukankan      html  css  js  c++  java
  • [Violet]蒲公英

    查看原题戳这里

    这是一道经典的分块题——用分块求区间众数。分块在线的时间复杂度为O( q sqrt(n) ),离线为O( n sqrt(n) )。

    分块可以进行区间操作,像求区间最值,区间和,区间修改等等。适用范围:分块>线段树>树状数组。

    用分块进行区间操作时,中间的完整的块可以通过预处理来完成,然后两头的就暴力for一下。

    下面是AC代码:

    #include<bits/stdc++.h>
    #define M 50500
    #define mc 500
    #define R register int
    using namespace std;
    struct Violet{int num,x,w;}a[M];
    //num 表示输入顺序
    //x 表示离散化之后的数
    //w 表示原数 
    int block,n,m,answer,tot;
    int s[M],sum[mc][M],ans[mc][mc],belong[M],color[M];
    //s[i] 是离散化之后的数与原数的映射
    //sum[i][j] 是离散化后每个数在每一块中的前缀和
    //ans[i][j] 表示第i-j块的众数
    //belong[i] 第i个数所在的块数
    //color[i] 表示离散化之后数i出现的次数 
    void first();
    void getsum(); 
    void getans();
    void sovle();
    void query(int,int);
    bool cmp1(Violet,Violet);
    bool cmp2(Violet,Violet);
    int main(){
        ios::sync_with_stdio(0);
        first();
        getsum();
        getans();
        sovle();
        return 0;
    }
    void first(){
        cin>>n>>m;
        block=sqrt(n);
        for(R i=1;i<=n;++i) cin>>a[i].w,a[i].num=i;
        sort(a+1,a+n+1,cmp1);
        for(R i=1;i<=n;++i){
            if(a[i].w!=a[i-1].w){
                s[++tot]=a[i].w;
                a[i].x=tot;
            }
            else a[i].x=a[i-1].x;
        }
        sort(a+1,a+n+1,cmp2);
    }
    void getsum(){
        for(R i=1;i<=n;++i){
            belong[i]=i/block;
            ++sum[belong[i]][a[i].x];
        }
        for(R i=0;i<=belong[n];++i)
          for(R j=1;j<=tot;++j)
            sum[i][j]+=sum[i-1][j];
    }
    void getans(){
        for(R i=0;i<=belong[n];++i){
            int be=i*block,now=0;
            if(!be) be=1;
            for(R j=be;j<=n;++j){
                if((++color[a[j].x] > color[now]) || (color[a[j].x] == color[now] && a[j].x<now)) now=a[j].x;
                ans[i][belong[j]]=now;
            }
            for(R j=be;j<=n;++j) --color[a[j].x];
        }
    }
    void sovle(){
        int l,r;
        for(R i=1;i<=m;++i){
            cin>>l>>r;
            l=(l+s[answer]-1)%n+1,r=(r+s[answer]-1)%n+1;
            if(l>r) query(r,l);
            else query(l,r);
        }
    }
    void query(int x,int y){
        int l=x/block+1,r=y/block-1;
        if(r-l<=1){
            answer=0;
            for(R i=x;i<=y;++i)
              if((++color[a[i].x] > color[answer]) || (color[a[i].x] == color[answer] && a[i].x < answer)) answer=a[i].x;
            for(R i=x;i<=y;++i) --color[a[i].x];
            printf("%d
    ",s[answer]);
            return;
        }
        else{
            answer=ans[l][r];
            for(R i=x;i<=l*block-1;++i)
              if(++color[a[i].x]+sum[r][a[i].x]-sum[l-1][a[i].x] > color[answer]+sum[r][answer]-sum[l-1][answer]) answer=a[i].x;
              else if(color[a[i].x]+sum[r][a[i].x]-sum[l-1][a[i].x] == color[answer]+sum[r][answer]-sum[l-1][answer] && a[i].x < answer) answer=a[i].x;
            for(R i=(r+1)*block;i<=y;++i)
              if(++color[a[i].x]+sum[r][a[i].x]-sum[l-1][a[i].x] > color[answer]+sum[r][answer]-sum[l-1][answer]) answer=a[i].x;
              else if(color[a[i].x]+sum[r][a[i].x]-sum[l-1][a[i].x] == color[answer]+sum[r][answer]-sum[l-1][answer] && a[i].x < answer) answer=a[i].x;
            for(R i=x;i<=l*block-1;++i) --color[a[i].x];
            for(R i=(r+1)*block;i<=y;++i) --color[a[i].x];
            printf("%d
    ",s[answer]);
            return;
        }
    }
    bool cmp1(Violet x,Violet y){return x.w<y.w;}
    bool cmp2(Violet x,Violet y){return x.num<y.num;}
  • 相关阅读:
    npm install遇到的问题
    已经安装了node和npm,输入node -v 未找到命令
    虚拟机VMware搭建代码环境
    使用VMware出现的各种问题
    bind、delegate、on的区别
    软件设计原则
    Qt 模型/视图/委托
    UML类图与类间六种关系表示
    C++内存分配与释放
    SQLite 自定义函数,聚合,排序规则
  • 原文地址:https://www.cnblogs.com/Glacier-elk/p/9767979.html
Copyright © 2011-2022 走看看