• 洛谷P4168 [Violet]蒲公英(分块)


    https://www.luogu.com.cn/problem/P4168

    分块大法好

    首先离散化把值域缩小到n

    预处理3个数组

    sum[i][j]表示前i块里j的出现次数

    mx[i][j]表示第i块到第j块出现次数最多的数出现了多少次

    who[i][j]表示第i块到第j块出现次数最多的数最小是谁

    对于查询

    如果左右端点在同一块或者相邻,就暴力求

    如果左右端点所在块中间至少隔着一块,

    假设左端点在第bl块,右端点在br块

    先直接通过mx和who获取bl+1到br-1块中出现次数最多的最小的数及出现次数

    然后只考虑在bl块里左端点后面的,以及在br块里右端点前面的数

    枚举这些数,先用一个数组记录在bl+1到br-1块中出现的次数

    然后再对他们累加左右端点所在块的出现次数,更新答案

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define N 50002
    
    int a[N],ha[N];
    
    int sum[251][N];
    int mx[251][251],who[251][251];
    
    int tmp[N];
    
    int main()
    {
        //freopen("P4168_1.in","r",stdin);
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) 
        {
            scanf("%d",&a[i]); 
            ha[i]=a[i];
        }
        sort(ha+1,ha+n+1);
        int nn=unique(ha+1,ha+n+1)-ha-1;
        for(int i=1;i<=n;++i) a[i]=lower_bound(ha+1,ha+nn+1,a[i])-ha;
        int siz=sqrt(n),s=(n-1)/siz+1,rr,rr2;
        for(int i=1;i<=s;++i)
        {
            for(int j=1;j<=nn;++j) 
            {
                sum[i][j]=sum[i-1][j];
                tmp[j]=0;
            }
            for(int j=1;j<i;++j)
            {
                mx[j][i]=mx[j][i-1];
                who[j][i]=who[j][i-1];
            }
            rr=min(n,i*siz);
            for(int j=(i-1)*siz+1;j<=rr;++j) 
            {
                sum[i][a[j]]++;
                for(int k=1;k<=i;++k)
                {
                    rr2=siz*k;
                    if(sum[i][a[j]]-sum[k-1][a[j]]>mx[k][i] || sum[i][a[j]]-sum[k-1][a[j]]==mx[k][i] && a[j]<who[k][i])
                    {
                        mx[k][i]=sum[i][a[j]]-sum[k-1][a[j]];
                        who[k][i]=a[j];
                    }
                }
            }
        }
        int l,r,bl,br,amx,awho,last=0;
        while(m--)
        {
            scanf("%d%d",&l,&r);
            l=(l+last-1)%n+1;
            r=(r+last-1)%n+1;
            if(l>r) swap(l,r); 
            bl=(l-1)/siz+1;
            br=(r-1)/siz+1;
            if(bl+1>=br)
            {
                amx=0;
                for(int i=l;i<=r;++i) tmp[a[i]]=0;    
                for(int i=l;i<=r;++i) 
                {
                    tmp[a[i]]++;
                    if(tmp[a[i]]>amx || tmp[a[i]]==amx && a[i]<awho)
                    {
                        amx=tmp[a[i]];
                        awho=a[i];
                    }
                }                    
            }
            else
            {
                amx=mx[bl+1][br-1];
                awho=who[bl+1][br-1];
                rr=bl*siz;
                rr2=(br-1)*siz+1;
                for(int i=l;i<=rr;++i) tmp[a[i]]=sum[br-1][a[i]]-sum[bl][a[i]];
                for(int i=rr2;i<=r;++i) tmp[a[i]]=sum[br-1][a[i]]-sum[bl][a[i]];
                for(int i=l;i<=rr;++i) 
                {
                    tmp[a[i]]++;
                    if(tmp[a[i]]>amx || tmp[a[i]]==amx && a[i]<awho)
                    {
                        amx=tmp[a[i]];
                        awho=a[i];
                    }
                }
                for(int i=rr2;i<=r;++i) 
                {
                    tmp[a[i]]++;
                    if(tmp[a[i]]>amx || tmp[a[i]]==amx && a[i]<awho)
                    {
                        amx=tmp[a[i]];
                        awho=a[i];
                    }
                }
            }
            last=ha[awho];
            printf("%d
    ",last);
        }
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    版本控制,django缓存,跨域问题解决
    Linux之文件系统结构
    Linux之定时任务
    Linux之LVM
    Linux之硬盘与分区
    Linux之文件重定向与查找
    Linux之文件压缩
    Linux之文件权限
    Linux之用户管理
    Linux之文件管理
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15158080.html
Copyright © 2020-2023  润新知