zoukankan      html  css  js  c++  java
  • 【BZOJ 2724】 蒲公英

    【题目链接】

                https://www.lydsy.com/JudgeOnline/problem.php?id=2724

    【算法】

                分块算法在线维护区间众数

                分块算法的精髓就在于 : 大段维护,局部朴素

                这一题,我们可以将序列分成T段,那么每一段的长度就是(N/T)

                对于每个询问,设l处于第p段,r处于第q段,那么 :

                若p = q,用朴素算法计算出区间众数即可

                否则,将这个序列分为三段 :

                1.[L,R[p]] 2. [L[p+1],R[q-1]] 3. [L[q],r]

                显然,区间众数只可能是 [L[p+1],R[q-1]]中的众数或[L,R[p]]中的一个数,或[L[q],r]中的一个数

                不妨预处理所有以“段边界”为端点每个数出现的次数和区间众数

        当T取sqrt3(N)(开三次方)时,时间复杂度是非常优秀的 : O(n^(5/3))

    【代码】

               

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 40010
    const int INF = 2e9;
    
    int i,j,k,n,m,l,r,l0,r0,lastans,t,block,len;
    int a[MAXN],val[MAXN],L[42],R[42],pos[MAXN],rk[MAXN];
    int cnt[42][42][MAXN],mx[42][42],d[42][42];
    
    inline int query(int l,int r)
    {
            int i;
            static int sum[MAXN];
            int mx = 0,ret = 0;
            int p = pos[l],q = pos[r];
            if (p == q)
            {
                    for (i = l; i <= r; i++)
                    {
                            sum[rk[i]]++;
                             if (sum[rk[i]] > mx || (sum[rk[i]] == mx && rk[i] < ret))
                             {
                                     mx = sum[rk[i]];
                                     ret = rk[i];
                             }
                    }        
                    for (i = l; i <= r; i++) sum[rk[i]]--;
                    return ret;
            }    else
            {
                    ret = d[p+1][q-1];
                    mx = cnt[p+1][q-1][ret];
                    for (i = l; i <= R[p]; i++) 
                    {
                            cnt[p+1][q-1][rk[i]]++;
                            if (cnt[p+1][q-1][rk[i]] > mx || (cnt[p+1][q-1][rk[i]] == mx && rk[i] < ret))
                            {
                                    mx = cnt[p+1][q-1][rk[i]];
                                    ret = rk[i];
                            }
                     }
                    for (i = L[q]; i <= r; i++)
                    {
                            cnt[p+1][q-1][rk[i]]++;
                            if (cnt[p+1][q-1][rk[i]] > mx || (cnt[p+1][q-1][rk[i]] == mx && rk[i] < ret))
                            {
                                    mx = cnt[p+1][q-1][rk[i]];
                                    ret = rk[i];
                            }
                    }
                    for (i = l; i <= R[p]; i++) cnt[p+1][q-1][rk[i]]--;
                    for (i = L[q]; i <= r; i++) cnt[p+1][q-1][rk[i]]--;
                    return ret;
            }
    } 
     
    int main() 
    {
            
            scanf("%d%d",&n,&m);
            for (i  = 1; i <= n; i++)
            {
                    scanf("%d",&a[i]);
                    val[++len] = a[i];
            }
            sort(val+1,val+len+1);
            len = unique(val+1,val+len+1) - val - 1;
            for (i = 1; i <= n; i++) rk[i] = lower_bound(val+1,val+len+1,a[i]) - val;
            block = (int)pow(n*1.0,1.0/3);
            if (block) t = n / block;
            for (i = 1; i <= block; i++)
            {
                    L[i] = (i - 1) * t + 1;
                    R[i] = i * t;
            }
            if (R[block] < n)
            {
                    block++;
                    L[block] = R[block-1] + 1;
                    R[block] = n;
            }
            for (i = 1; i <= block; i++)
            {
                    for (j = L[i]; j <= R[i]; j++)
                    {
                            pos[j] = i;
                    }
            }
            for (i = 1; i <= block; i++)
            {
                    for (j = i; j <= block; j++)
                    {
                            for (k = L[i]; k <= R[j]; k++)
                                    cnt[i][j][rk[k]]++;
                            for (k = 1; k <= len; k++)
                            {
                                    if (cnt[i][j][k] > mx[i][j] || (cnt[i][j][k] == mx[i][j] && k < d[i][j]))
                                    {
                                            mx[i][j] = cnt[i][j][k];
                                            d[i][j] = k;
                                    }
                            }
                    }        
            }
            lastans = 0;
            for (i = 1; i <= m; i++)
            {
                    scanf("%d%d",&l0,&r0);
                    l = (l0 + lastans - 1) % n + 1; 
                    r = (r0 + lastans - 1) % n + 1;
                    if (l > r) swap(l,r);
                    printf("%d
    ",lastans = val[query(l,r)]);            
            }
            
            return 0;
        
    }
  • 相关阅读:
    async await promise 执行时序
    理解prototype
    X-Requested-With
    event事件传播规则
    【小文】Flask web Hello程序!
    【小文】php-gtk: Hello!
    【小文】HTTP 状态码
    【小文】Python环境安装配置
    C语言:趣味小问题 鸡兔同笼
    C语言:趣味小问题 百钱买百鸡
  • 原文地址:https://www.cnblogs.com/evenbao/p/9309581.html
Copyright © 2011-2022 走看看