• [bzoj4241]历史研究


    来自FallDream的博客,未经允许,请勿转载,谢谢。


    IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记。JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件。
    日记中记录了连续N天发生的时间,大约每天发生一件。
    事件有种类之分。第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大。
    JOI教授决定用如下的方法分析这些日记:
    1. 选择日记中连续的一些天作为分析的时间段
    2. 事件种类t的重要度为t*(这段时间内重要度为t的事件数)
    3. 计算出所有事件种类的重要度,输出其中的最大值
    现在你被要求制作一个帮助教授分析的程序,每次给出分析的区间,你需要输出重要度的最大值。
    n,m<=10^5
     
     
    考虑莫队,但是要避免删除操作,所以考虑只移动右端点,然后每次移动一下左端点计算答案再移动回去,复杂度$O(nsqrt{n})$
    如果强制在线的话,可以分块,块与块之间的答案预处理,然后块外枚举一下在vector里面二分即可,块大小大概$sqrt{frac{n}{logn}}$,复杂度$O(nsqrt{nlogn})$
    莫队
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define MN 100000
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    ll ans[MN+5],f[MN+5],mx;
    int n,m,l[MN+5],a[MN+5],tot=1,block[MN+5],size,L,R;
    struct ques{int l,r,id;}q[MN+5];
    bool cmp(ques x,ques y){return block[x.l]==block[y.l]?x.r<y.r:x.l<y.l;}
    
    int main()
    {
        n=read();m=read();size=sqrt(n);
        for(int i=1;i<=n;++i) block[i]=(i-1)/size+1;
        for(int i=1;i<=n;++i) a[i]=l[i]=read();
        for(int i=1;i<=m;++i) q[i].l=read(),q[i].r=read(),q[i].id=i;
        sort(q+1,q+m+1,cmp);sort(l+1,l+n+1);
        for(int i=2;i<=n;++i) if(l[i]!=l[i-1]) l[++tot]=l[i];
        for(int i=1;i<=n;++i) a[i]=lower_bound(l+1,l+tot+1,a[i])-l;
        for(int i=1,last=0;i<=m;++i)
        {
            if(block[q[i].l]!=last)
            {
                memset(f,0,sizeof(f));
                R=(last=block[q[i].l])*size+1;
                mx=f[a[R]]=l[a[R]];
            }
            if(block[q[i].l]==block[q[i].r])
            {
                f[a[R]]-=l[a[R]];ll Ans=0;
                for(int j=q[i].l;j<=q[i].r;++j)
                    Ans=max(Ans,f[a[j]]+=l[a[j]]);
                ans[q[i].id]=Ans;
                for(int j=q[i].l;j<=q[i].r;++j)
                    f[a[j]]-=l[a[j]];
                f[a[R]]+=l[a[R]];
            }
            else 
            { 
                while(R<q[i].r) ++R,mx=max(mx,f[a[R]]+=l[a[R]]);
                ans[q[i].id]=mx;
                for(int j=block[q[i].l]*size;j>=q[i].l;--j) 
                    ans[q[i].id]=max(ans[q[i].id],f[a[j]]+=l[a[j]]);
                for(int j=block[q[i].l]*size;j>=q[i].l;--j) 
                    f[a[j]]-=l[a[j]];
            } 
        }
        for(int i=1;i<=m;++i) printf("%lld
    ",ans[i]);
        return 0;
    }

    分块

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring> 
    #include<cmath>
    #include<vector>
    #define MN 100000
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    ll f[MN+5],ans[1280][1280];
    int n,m,l[MN+5],a[MN+5],tot=1,size,block[MN+5],L,R;
    struct ques{int l,r,id;}q[MN+5];
    vector<int> v[MN+5];
    
    ll Get(int x,int L,int R)
    {
        int num=upper_bound(v[x].begin(),v[x].end(),R)-lower_bound(v[x].begin(),v[x].end(),L);
        return 1LL*num*l[x];    
    }
    
    ll Bl(int l,int r)
    {
        ll ans=0;    
        for(int i=l;i<=r;++i) ans=max(ans,Get(a[i],l,r));
        return ans;
    }
    
    int main()
    {
        n=read();m=read();size=max(1,(int)sqrt(n/16));
        for(int i=1;i<=n;++i) block[i]=(i-1)/size+1;
        for(int i=1;i<=n;++i) a[i]=l[i]=read();
        sort(l+1,l+n+1);
        for(int i=2;i<=n;++i) if(l[i]!=l[i-1]) l[++tot]=l[i];
        for(int i=1;i<=n;++i) v[a[i]=lower_bound(l+1,l+tot+1,a[i])-l].push_back(i);
        for(int i=1;i<=n;i+=size)
        {
            memset(f,0,sizeof(f));ll mx=0;
            for(int j=i;j<=n;++j)
            {
                mx=max(mx,f[a[j]]+=l[a[j]]);
                if(j%size==0||j==n) ans[block[i]][block[j]]=mx;
            }
        }
        for(int i=1;i<=m;++i)
        {
            int l=read(),r=read();
            if(block[l]==block[r]) printf("%lld
    ",Bl(l,r));
            else 
            {
                ll Ans=ans[block[l]+1][block[r]-1]; 
                for(int i=l;block[i]==block[l];++i)
                    Ans=max(Ans,Get(a[i],l,r));
                for(int i=r;block[i]==block[r];--i)
                    Ans=max(Ans,Get(a[i],l,r)); 
                printf("%lld
    ",Ans);
            }
        }
        return 0;
    }
     
  • 相关阅读:
    路由
    更改HTTP头信息
    laravel 笔记
    laraven安装记录
    虚拟机Centos设置静态IP
    关于正向代理,反向代理,负载均衡的个人理解
    exce族函数详解
    【C】多线程编程笔记
    【转】Linux C 网络编程——TCP套接口编程
    MySQL 用户管理及权限管理
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj4241.html
Copyright © 2020-2023  润新知