zoukankan      html  css  js  c++  java
  • 数列分块9

    写一下分块,写的是洛谷的强制在线版本,写完之后感觉有一些实现上的细节处理可以整理一下。

    首先简单说说分块怎么写。

    我们还是按照 (sqrt n) 的大小分块,然后进行预处理。我们定义 (sum[i][j]) 为前 i 个块中 j 出现了多少次,(dp[i][j]) 为块 i 和块 j 中的众数是哪一个。

    我们根据分块的思想来想,每一个询问区间都可以看做中间的完整块和左右的零散元素。我们想询问众数的话哪些数有可能成为众数。显然只有中间整块部分的众数,以及左右部分的元素可能成为答案,证明自证(滑稽)

    我们可以枚举左右零散部分的元素加到一个桶里面,每次加进去就看一下能否更新答案即可

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    #define B printf("!");
    #define calc(x) sum[col[r]-1][x]-sum[col[l]][x]
    using namespace std;
    
    int read()
    {
        int a = 0,x = 1;char ch = getchar();
        while(ch > '9' || ch < '0') {if(ch == '-') x = -1;ch = getchar();}
        while(ch >= '0' && ch <= '9') {a = a*10 + ch-'0';ch = getchar();}
        return a*x;
    }
    const int N=4e4+1,M=2e2+7;
    int n,m,b,col[N],que[N],a[N],pos[N];
    int sum[M][N],t[N],dp[M][M],qwq = 999;
    
    int query(int l,int r)
    {
        if(col[r]-col[l] <= 1) {
            int maxn = 0;
            for(int i = l;i <= r;i ++) {
                t[a[i]] ++;
                if(t[a[i]] > t[maxn] || (t[a[i]] == t[maxn] && a[i] < maxn)) maxn = a[i];
            }
            for(int i = l;i <= r;i ++) t[a[i]] --;
            return maxn;
        }
        int maxn = dp[col[l]+1][col[r]-1];
        for(int i = l;col[i] == col[l];i ++) {
            t[a[i]] ++;
            if(t[a[i]]+calc(a[i]) > t[maxn]+calc(maxn) || (t[a[i]]+calc(a[i]) == t[maxn]+calc(maxn) && a[i] < maxn))
                maxn = a[i];
        }
    
        for(int i = r;col[i] == col[r];i --) {
            t[a[i]] ++;
            if(t[a[i]]+calc(a[i]) > t[maxn]+calc(maxn) || (t[a[i]]+calc(a[i]) == t[maxn]+calc(maxn) && a[i] < maxn))
                maxn = a[i];
        }
        for(int i = l;col[i] == col[l];i ++) t[a[i]] --;
        for(int i = r;col[i] == col[r];i --) t[a[i]] --;
        return maxn;
    }
    
    int main()
    {
        freopen("in.in","r",stdin);
        freopen("out.out","w",stdout);
        n = read(),m = read();b = sqrt(n);
        for(int i = 1;i <= n;i ++) a[i] = que[i] = read();
        for(int i = 1;i <= n;i ++) col[i] = (i-1)/b+1;
        sort(que+1,que+1+n);int len = unique(que+1,que+1+n) - que - 1;
        for(int i = 1,tmp;i <= n;i ++) a[i] = lower_bound(que+1,que+1+len,tmp=a[i]) - que,pos[a[i]] = tmp;
        for(int i = 1;i <= n;i ++) for(int j = col[i];j <= col[n];j ++) sum[j][a[i]] ++;
        for(int i = 1,maxn=0;i <= col[n];i ++) {
            for(int j = b*(i-1)+1;j <= n;j ++) {
                t[a[j]] ++;
                if(t[a[j]] > t[maxn] || (t[a[j]] == t[maxn] && a[j] < maxn)) maxn = a[j];
                dp[i][col[j]] = maxn;
            }
            memset(t,0,sizeof(t));maxn = 0;
        }
    
        for(int i = 1,x = 0;i <= m;i ++) {
                int l = read(),r = read();
                l = (l+x-1)%n+1,r = (r+x-1)%n+1;
                if(l > r) swap(l,r);
                printf("%d
    ",x=pos[query(l,r)]);
        }
        return 0;
    }
    
  • 相关阅读:
    【转】批处理第三方命令行工具汇总(2014-11-10更新)
    爬虫问题汇总 + 解决
    ocs的沟通平台
    DSCP 与IP 优先级IP优先级
    IPSec协议
    GRE 协议简介
    使用VLC创建组播流
    华为olt ma5680t常用命令详解
    Python统计列表中的重复项出现的次数的方法
    Kafka
  • 原文地址:https://www.cnblogs.com/nao-nao/p/13962297.html
Copyright © 2011-2022 走看看