zoukankan      html  css  js  c++  java
  • bzoj4241 历史研究——分块

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4241

    就是分块,预处理出从第 i 块到 j 位置的答案,以及从第 i 块到最后位置间每个数出现的次数;

    然后块内统计、块外暴力即可。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int const maxn=1e5+5;
    int n,q,a[maxn],b[maxn],cnt[333][maxn],sta[maxn],top,m,tot,blk[maxn],num[maxn];
    ll f[333][maxn];
    int main()
    {
        scanf("%d%d",&n,&q); tot=sqrt(n);
        for(int i=1;i<=n;i++)blk[i]=(i-1)/tot+1;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
        sort(b+1,b+n+1); m=unique(b+1,b+n+1)-b-1;
        for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+m+1,a[i])-b;
        for(int i=1;i<=blk[n];i++)
        {
            ll nw=0;
            for(int j=lower_bound(blk+1,blk+n+1,i)-blk;j<=n;j++)
                cnt[i][a[j]]++,nw=max(nw,(ll)cnt[i][a[j]]*b[a[j]]),f[i][j]=nw;//cnt是第i块a[j]数量后缀
                //f[i][j]表示第i块到j位置的答案 
        }
        for(int i=1,x,y;i<=q;i++)
        {
            scanf("%d%d",&x,&y);
            ll ans=f[blk[x]+1][y];
            int st=lower_bound(blk+1,blk+n+1,blk[y])-blk;
            for(int i=st;i<=y;i++)num[a[i]]++,sta[++top]=a[i];
            st=lower_bound(blk+1,blk+n+1,blk[x]+1)-blk;
            for(int i=x;i<st;i++)
            {
                num[a[i]]++;
                ans=max(ans,(ll)(cnt[blk[x]+1][a[i]]-cnt[blk[y]][a[i]]+num[a[i]])*b[a[i]]);
                sta[++top]=a[i];
            }
            printf("%lld
    ",ans);
            while(top)num[sta[top]]=0,top--;//不用memset 
        }
        return 0;
    }
  • 相关阅读:
    SQL作业的操作全
    ISAPI Rewrite 实现简单url重写、二级域名重写
    wwf mvc学习
    如何扩大内需
    惊喜
    无限级分类查询
    杂记
    20130118SQL记录
    百度调价HttpWebRequest
    检查外链的方法
  • 原文地址:https://www.cnblogs.com/Zinn/p/9298037.html
Copyright © 2011-2022 走看看