Loading [MathJax]/jax/element/mml/optable/SuppMathOperators.js

[Ynoi2019模拟赛]Yuno loves sqrt technology III

题目大意:

给你一个长为n的序列am次询问,每次查询一个区间的众数的出现次数,强制在线。

解题思路:

出题人题解

众所周知lxl是个毒瘤,Ynoi道道都是神仙题

首先得离散化。

分块后,预处理Fi,j表示第ij块的众数的出现次数。此处要用一个桶,空间复杂度O(n),时间复杂度O(nn)

用vector按顺序存每个数值所有元素的出现位置。

再记录每个元素在相应vector里的下标p

以上空间复杂度都是O(n)的。

考虑询问,中间的直接使用预处理出的Fi,j的值即可。设当前的答案ans=Fi,j

考虑边界的元素。

显然,由于边界的数最多2n个,所以最多使得答案增加2n

我们只需要检查这些边角的元素,每次判断这些数的出现次数能否达到ans+1

对于左边的边角元素x,我们在相应的vector里找到下标为px+ans的元素y,若y,则说明该数值在范围内有至少ans+1个数,暴力++ans即可。

对于右边的边角元素x,我们在相应的vector里找到下标为p_x-ans的元素y,若y\geqslant l,则说明该数值在范围内有至少ans+1个数,暴力++ans即可。

每次询问对O(\sqrt n)个元素检查,++ans的次数为O(\sqrt n)次。所以查询的时间复杂度为O(m\sqrt n)

总时间复杂度O((n+m)\sqrt n),空间复杂度O(n),lxl说达到了下界。

C++ Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<algorithm>
#define siz 708
#define N 500001
class istream{
    char buf[20000003],*s;
    public:
        inline istream(){
#ifndef ONLINE_JUDGE
            freopen("input.txt","r",stdin);
#endif
            fread(s=buf,1,20000003,stdin);
            fclose(stdin);
        }
        inline istream&operator>>(int&rhs){
            int f=rhs=0;
            for(;!isdigit(*s);++s)f=*s=='-';
            for(;isdigit(*s);)
            rhs=(rhs<<3)+(rhs<<1)+(*s++^'0');
            if(f)rhs=-rhs;
            return*this;
        }
}cin;
class ostream{
    char buf[5000005],*s;
    public:
        inline ostream(){s=buf;}
        inline ostream&operator<<(int rhs){
            if(rhs<0)*s++='-',rhs=-rhs;
            if(rhs==0){
                *s++='0';
                return*this;
            }
            static int w;
            for(w=1;w<=rhs;w*=10);
            for(w/=10;w;w/=10)*s++=(rhs/w)^'0',rhs%=w;
            return*this;
        }
        inline ostream&operator<<(const char&rhs){*s++=rhs;return*this;}
        inline~ostream(){
            fwrite(buf,1,s-buf,stdout);
        }
}cout;
int n,m,L[710],R[710],bel[N],blocks,mx[710][710],ans,tot[N],wz[N],a[N];
void init(){
    blocks=(n-1)/siz+1;
    for(int i=1;i<=blocks;++i)L[i]=R[i-1]+1,R[i]=i*siz;
    R[blocks]=n;
    for(int i=1;i<=blocks;++i){
        memset(tot,0,sizeof tot);
        for(int j=L[i];j<=R[i];++j)bel[j]=i;
        for(int j=i;j<=blocks;++j){
            int&F=mx[i][j];
            F=mx[i][j-1];
            for(int k=L[j];k<=R[j];++k)
            F=std::max(F,++tot[a[k]]);
        }
    }
}
std::vector<int>ls,v[N];
int main(){
    ls.push_back(-1);
    cin>>n>>m;
    for(int i=1;i<=n;ls.push_back(a[i++]))cin>>a[i];
    std::sort(ls.begin(),ls.end());
    ls.erase(std::unique(ls.begin(),ls.end()),ls.end());
    for(int i=1;i<=n;++i)v[a[i]=std::lower_bound(ls.begin(),ls.end(),a[i])-ls.begin()].push_back(i),wz[i]=v[a[i]].size()-1;
    init();
    memset(tot,0,sizeof tot);
    while(m--){
        int l,r;cin>>l>>r;
        l^=ans,r^=ans;
        ans=0;
        if(bel[l]==bel[r]){
            for(int i=l;i<=r;++i)ans=std::max(ans,++tot[a[i]]);
            for(int i=l;i<=r;++i)tot[a[i]]=0;
        }else{
            ans=mx[bel[l]+1][bel[r]-1];
            for(int i=l;i<=R[bel[l]];++i){
                int it=wz[i];
                while(it+ans<v[a[i]].size()&&v[a[i]][it+ans]<=r)++ans;
            }
            for(int i=L[bel[r]];i<=r;++i){
                int it=wz[i];
                while(it-ans>=0&&v[a[i]][it-ans]>=l)++ans;
            }
        }
        cout<<ans<<'\n';
    }
    return 0;
}

 

posted @   Mrsrz  阅读(338)  评论(0编辑  收藏  举报
编辑推荐:
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
阅读排行:
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Huawei LiteOS基于Cortex-M4 GD32F4平台移植
· mysql8.0无备份通过idb文件恢复数据过程、idb文件修复和tablespace id不一致处
点击右上角即可分享
微信分享提示