zoukankan      html  css  js  c++  java
  • E 仓鼠与珂朵莉(WHU新生赛)

    题目链接:https://ac.nowcoder.com/acm/contest/8925/E

    题意:定义一个区间的重要程度:max(k*k在区间中的个数)(k为区间中的数),有m个查询操作,求区间[l,r]间的重要程度。(强制在线)

    思路:本题是“暴力美学”的杰出代表,使用分块可以O(n√n)内完成。首先由于区间中的数在[0,1e9]的范围内,所以先用离散化。要使用分块,那就要求出整大块的答案,左右两边不成块的数在O(√n)内处理即可。所以我们需求出第i块到第j块的重要程度f[i][j],暴力枚举左起的i,然后向右处理出f[i][j]即可,复杂度为O(n√n)。至于如何处理零散数,可以维护h[i][j]表示第i块数j的个数,枚举零散数并加上整块中该数的个数从而来维护区间重要程度。但是这么做的话,每次把整块的数的的个数加起来时需要O(√n)的复杂度,时间显然爆表。因此,用前缀和维护h[i][j]即可。

    总步骤:离散化---->分块---->预处理f[i][j]和前缀和sum[i][j]---->进行计算操作(整块、零散)

    代码:

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define LL long long
    LL n,m,a[100100],b[100100],cnt;
    LL l[320],r[320],blo,num,bel[100100];
    LL vis[100100],sum[320][100100],f[320][320];
    void lisan()
    {
        sort(b+1,b+n+1);
        cnt=unique(b+1,b+n+1)-b-1;
        for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
        return;
    }
    void fk()
    {
        blo=sqrt(n);
        num=n/blo;
        if (n%blo) num++;
        for(int i=1;i<=num;i++) {l[i]=(i-1)*blo+1; r[i]=i*blo;}
        r[num]=n;
        for(int i=1;i<=n;i++) bel[i]=(i-1)/blo+1;
        return;
    }
    void init()
    {
        LL now;
        for(int i=1;i<=num;i++)
        {
            now=0;
            for(int j=i;j<=num;j++)
            {
                for(int k=l[j];k<=r[j];k++)
                {
                    vis[a[k]]++;
                    now=max(now,vis[a[k]]*b[a[k]]);
                }
                f[i][j]=now;
            }
            for(int j=l[i];j<=n;j++) vis[a[j]]--;
            for(int j=l[i];j<=r[i];j++) sum[i][a[j]]++;
        }
        for(int i=1;i<=num;i++)
        for(int j=1;j<=cnt;j++)
        sum[i][j]+=sum[i-1][j];
        return;
    }
    LL calc(LL ll,LL rr)
    {
        LL nl,nr,ret;
        if (l[bel[ll]]==ll) nl=bel[ll];
        else nl=bel[ll]+1;
        if (r[bel[rr]]==rr) nr=bel[rr];
        else nr=bel[rr]-1;
        ret=0;
        if (nl!=bel[ll])
        {
            for(int i=ll;i<=r[bel[ll]];i++)
            {
                vis[a[i]]++;
                ret=max(ret,(vis[a[i]]+sum[nr][a[i]]-sum[nl-1][a[i]])*b[a[i]]);
            }
        }
        if (nr!=bel[rr])
        {
            for(int i=l[bel[rr]];i<=rr;i++)
            {
                vis[a[i]]++;
                ret=max(ret,(vis[a[i]]+sum[nr][a[i]]-sum[nl-1][a[i]])*b[a[i]]);
            }
        }
        if (nl<=nr) ret=max(ret,f[nl][nr]);
        if (nl!=bel[ll])
        for(int i=ll;i<=r[bel[ll]];i++) vis[a[i]]--;
        if (nr!=bel[rr])
        for(int i=l[bel[rr]];i<=rr;i++) vis[a[i]]--;
        return ret;
    }
    int main()
    {
        LL ans=0,ll,rr;
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++) {scanf("%lld",&a[i]); b[i]=a[i];}
        lisan();
        fk();
        init();
        for(int i=1;i<=m;i++)
        {
            scanf("%lld%lld",&ll,&rr);
            ll=(ll^ans)%n+1;
            rr=(rr^ans)%n+1;
            if (ll>rr) ll^=rr^=ll^=rr;
            ans=calc(ll,rr);
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Java NIO系列教程(九) ServerSocketChannel
    Java NIO系列教程(十) Java NIO DatagramChannel
    Java NIO系列教程(七) FileChannel
    Java NIO系列教程(八) SocketChannel
    Java NIO系列教程(六) Selector
    Java NIO系列教程(四) Scatter/Gather
    简述数据库设计的范式及应用
    简述在MySQL数据库中MyISAM和InnoDB的区别
    sql语句_2
    sql语句_统计总成绩最高的前2名
  • 原文地址:https://www.cnblogs.com/ctrl-newbee/p/14055649.html
Copyright © 2011-2022 走看看