• BZOJ4241 历史研究(莫队)


      如果分块的话与区间众数没有本质区别。这里考虑莫队。

      显然莫队时的删除可以用堆维护,但多了一个log不太跑得过。

      有一种叫回滚莫队的trick,可以将问题变为只有加入操作。按莫队时分的块依次处理,一块中左端点的差不超过√n,右端点单调递增。首先将右端点也在该块中的询问暴力处理。然后令指针l在下一块开头,指针r在这一块结尾。暴力扩展右端点移动指针r,到达询问点时,移动指针l以回答询问,但不让指针l的移动对之后的询问产生影响,即回滚。这样就可以处理删除了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 100010
    #define ll long long
    int n,m,a[N],b[N],cnt[N];
    ll ans[N];
    struct data
    {
        int x,y,k,i;
        bool operator <(const data&a) const
        {
            return k<a.k||k==a.k&&y<a.y;
        }
    }q[N];
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4241.in","r",stdin);
        freopen("bzoj4241.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=n;i++) b[i]=a[i]=read();
        sort(b+1,b+n+1);
        int t=unique(b+1,b+n+1)-b-1;
        for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+t+1,a[i])-b;
        int block=sqrt(n);
        for (int i=1;i<=m;i++) q[i].x=read(),q[i].y=read(),q[i].k=q[i].x/block,q[i].i=i;
        sort(q+1,q+m+1);
        for (int i=1;i<=m;i++)
        {
            int t=i;while (t<m&&q[t+1].k==q[i].k) t++;
            while (i<=t&&q[i].y<(q[i].k+1)*block)
            {
                for (int j=q[i].x;j<=q[i].y;j++)
                {
                    cnt[a[j]]++;
                    ans[q[i].i]=max(ans[q[i].i],1ll*cnt[a[j]]*b[a[j]]);
                }
                for (int j=q[i].x;j<=q[i].y;j++) cnt[a[j]]--;
                i++;
            }
            int r=(q[i].k+1)*block-1;ll v=0;
            for (int j=i;j<=t;j++)
            {
                while (r<q[j].y)
                {
                    cnt[a[++r]]++;
                    v=max(v,1ll*cnt[a[r]]*b[a[r]]);
                }
                ans[q[j].i]=v;
                for (int k=(q[i].k+1)*block-1;k>=q[j].x;k--)
                {
                    cnt[a[k]]++;
                    ans[q[j].i]=max(ans[q[j].i],1ll*cnt[a[k]]*b[a[k]]);
                }
                for (int k=(q[i].k+1)*block-1;k>=q[j].x;k--) cnt[a[k]]--;
            }
            memset(cnt,0,sizeof(cnt));
            i=t;
        }
        for (int i=1;i<=m;i++) printf(LL,ans[i]);
        return 0;
    }
  • 相关阅读:
    obj,lib,dll,exe
    .net连接access数据库 关键字引起的 语句的语法错误
    XSS攻击与防御
    location.href和location.replace和location.reload的不同(location.replace不记录历史)
    C++中头文件包含问题
    SqlServerExpress2005 自动备份
    在SQL Server 的使用过程中,发现几个很有用,但不太常用
    双机镜像
    浅谈SQL Server identity列的操作方法
    镜像三机
  • 原文地址:https://www.cnblogs.com/Gloid/p/9833040.html
Copyright © 2020-2023  润新知