LOJ6285 数列分块入门9(分块)

本文分享了在解决Loj数列分块入门题目的过程中遇到的挑战及解决方案,包括调整块大小避免TLE,使用map进行离散化时的注意事项,以及具体的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天对着代码看了一晚上
然后今天终于在loj上过了
数列分块入门9题撒花★,°:.☆( ̄▽ ̄)/$:.°★

然后相当玄学
块的大小调成\(\sqrt{n}\)会TLE,改成150就过了

然后就是用map离散化之后的值不能直接比较大小
锅锅锅

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <cmath>
using namespace std;
int belong[100100],f[1000][1000],sz,blocknum,n,val[100100],id=0,cnt[100100],a[100100];
vector<int> Vec[100100];
map<int,int> To;
void calbe(int n){
    for(int i=1;i<=n;i++)
        belong[i]=(i-1)/sz+1;
}
void pre(int x){
    memset(cnt,0,sizeof(cnt));
    int ans=0,ansto=0;
    for(int i=(x-1)*sz+1;i<=n;i++){
        cnt[a[i]]++;
        if(cnt[a[i]]>ansto||(val[a[i]]<=val[ans]&&cnt[a[i]]>=ansto))
            ans=a[i],ansto=cnt[a[i]];
        f[x][belong[i]]=ans;
    }
}
int query(int l,int r,int c){
    return upper_bound(Vec[c].begin(),Vec[c].end(),r)-lower_bound(Vec[c].begin(),Vec[c].end(),l);
}
int query(int l,int r){
    int lsx=belong[l];
    int rex=belong[r];
    int ans=0,ansto=0,mid;
    for(int i=l;i<=min(lsx*sz,r);i++)
        if((mid=query(l,r,a[i]))>ansto||(val[a[i]]<=val[ans]&&mid>=ansto))
            ans=a[i],ansto=mid;
    if(lsx!=rex){
        for(int i=(rex-1)*sz+1;i<=r;i++)
            if((mid=query(l,r,a[i]))>ansto||(val[a[i]]<=val[ans]&&mid>=ansto))
                ans=a[i],ansto=mid;
        if(lsx+1<=rex-1)
            if((mid=query(l,r,f[lsx+1][rex-1]))>ansto||(val[f[lsx+1][rex-1]]<=val[ans]&&mid>=ansto))
                ans=f[lsx+1][rex-1],ansto=mid;
    }
    return ans;
}
int main(){
    // freopen("1.in","r",stdin);
    // freopen("test.out","w",stdout);
    scanf("%d",&n);
    sz=150;
    blocknum=n/sz;
    if(n%sz)    
        blocknum++;
    calbe(n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if(!To[a[i]]){
            To[a[i]]=++id;
            val[id]=a[i];
        }
        a[i]=To[a[i]];
        Vec[a[i]].push_back(i);
    }
    for(int i=1;i<=blocknum;i++)
        pre(i);
    for(int i=1;i<=n;i++){
        int l,r;
        scanf("%d %d",&l,&r);
        printf("%d\n",val[query(l,r)]);
    }
    return 0;    
}

转载于:https://www.cnblogs.com/dreagonm/p/10048516.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值