求卡常
查看原帖
求卡常
437398
EastIsRed楼主2024/6/19 20:04

从第8个测试点开始TLE,线下 n=100000,m=300000n=100000,m=300000 随机数据预处理和读入加起来不超过0.5s,询问部分用时7~8s,求卡常

#include<cstdio>
#include<algorithm>
#include<ctime>
constexpr int MAXN=100002,LEN_BLOCK=288;
int n,m,a[MAXN],id[MAXN],rk[MAXN],block_n;
int arr[(MAXN+LEN_BLOCK-1)/LEN_BLOCK][LEN_BLOCK],arr_tot[(MAXN+LEN_BLOCK-1)/LEN_BLOCK];
int mn[(MAXN+LEN_BLOCK-1)/LEN_BLOCK][LEN_BLOCK][LEN_BLOCK];
int mx[(MAXN+LEN_BLOCK-1)/LEN_BLOCK][LEN_BLOCK][LEN_BLOCK];
int res_in_block[(MAXN+LEN_BLOCK-1)/LEN_BLOCK][LEN_BLOCK][LEN_BLOCK];
short before[(MAXN+LEN_BLOCK-1)/LEN_BLOCK][MAXN],after[(MAXN+LEN_BLOCK-1)/LEN_BLOCK][MAXN];
inline int abs(int a)
{
    return a<0?-a:a;
}
inline int read()
{
    int m=0;
    char ch=getchar();
    while(ch>'9'||ch<'0')
        ch=getchar();
    while(ch>='0'&&ch<='9')
    {
        m=(m<<3)+(m<<1)+(ch^48);
        ch=getchar();
    }
    return m;
}
inline bool cmp(int u,int v) {return a[u]<a[v];}
inline void chk_min(int& u,int v) {u>v?u=v:0;}
inline void chk_max(int& u,int v) {u<v?u=v:0;}
int main()
{
    // freopen("CF765F.in","r",stdin);
    // freopen("CF765F.out","w",stdout);
    // clock_t st=clock();
    n=read();
    block_n=(n+LEN_BLOCK-1)/LEN_BLOCK;
    for(int i=1;i<=n;i++)
        a[i]=read(),id[i]=i;
    // fprintf(stderr,"until input use time %.6lf seconds\n",double(clock()-st)/CLOCKS_PER_SEC);
    std::sort(id+1,id+1+n,cmp);
    for(int i=1;i<=n;i++)
        rk[id[i]]=i;
    for(int i=1;i<=n;i++)
    {
        int bel=(rk[i]-1)/LEN_BLOCK;
        arr[bel][arr_tot[bel]++]=i;
    }
    for(int i=0;i<block_n;i++)
    {
        for(int j=0;j<arr_tot[i];j++)
        {
            res_in_block[i][j][j]=2e9+7;
            for(int k=j+1;k<arr_tot[i];k++)
                res_in_block[i][j][k]=std::min(res_in_block[i][j][k-1],abs(a[arr[i][k]]-a[arr[i][j]]));
        }
        for(int j=arr_tot[i]-2;j>=0;j--)
            for(int k=j+1;k<arr_tot[i];k++)
                chk_min(res_in_block[i][j][k],res_in_block[i][j+1][k]);
        for(int j=0;j<=n+1;j++)
            before[i][j]=-1,after[i][j]=32000;
        for(int j=0;j<arr_tot[i];j++)
        {
            mn[i][j][j]=mx[i][j][j]=a[arr[i][j]];
            for(int k=j+1;k<arr_tot[i];k++)
                mn[i][j][k]=std::min(mn[i][j][k-1],a[arr[i][k]]),
                mx[i][j][k]=std::max(mx[i][j][k-1],a[arr[i][k]]);
            before[i][arr[i][j]]=after[i][arr[i][j]]=j;
        }
        for(int j=n;j>=1;j--)
            if(after[i][j]==32000)
                after[i][j]=after[i][j+1];
        for(int j=1;j<=n;j++)
            if(before[i][j]==-1)
                before[i][j]=before[i][j-1];
    }
    // fprintf(stderr,"until pre processing use %.6lf seconds\n",double(clock()-st)/CLOCKS_PER_SEC);
    m=read();
    while(m--)
    {
        int l=read(),r=read(),res=2e9+7,cur_mx=-1;
        for(int i=0;i<block_n;i++)
        {
            int nl=after[i][l],nr=before[i][r];
            if(nl>nr) continue;
            if(cur_mx!=-1)
                chk_min(res,mn[i][nl][nr]-cur_mx);
            chk_min(res,res_in_block[i][nl][nr]);
            chk_max(cur_mx,mx[i][nl][nr]);
        }
        printf("%d\n",res);
    }
    // fprintf(stderr,"until finish use %.6lf seconds\n",double(clock()-st)/CLOCKS_PER_SEC);
    return 0;
}
2024/6/19 20:04
加载中...