zoukankan      html  css  js  c++  java
  • [bzoj4241] 历史研究 (分块)

    传送门

    Description

    IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记。JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件。
    日记中记录了连续N天发生的时间,大约每天发生一件。
    事件有种类之分。第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大。
    JOI教授决定用如下的方法分析这些日记:

    1. 选择日记中连续的一些天作为分析的时间段
    2. 事件种类t的重要度为t*(这段时间内重要度为t的事件数)
    3. 计算出所有事件种类的重要度,输出其中的最大值
      现在你被要求制作一个帮助教授分析的程序,每次给出分析的区间,你需要输出重要度的最大值。

    Input

    第一行两个空格分隔的整数N和Q,表示日记一共记录了N天,询问有Q次。
    接下来一行N个空格分隔的整数X1...XN,Xi表示第i天发生的事件的种类
    接下来Q行,第i行(1<=i<=Q)有两个空格分隔整数Ai和Bi,表示第i次询问的区间为[Ai,Bi]。

    Output

    输出Q行,第i行(1<=i<=Q)一个整数,表示第i次询问的最大重要度

    Sample Input

    5 5

    9 8 7 8 9

    1 2

    3 4

    4 4

    1 4

    2 4

    Sample Output

    9

    8

    8

    16

    16

    HINT

    1<=N<=10^5

    1<=Q<=10^5

    1<=Xi<=10^9 (1<=i<=N)

    Solution

    先分块预处理出后缀答案(顺便处理出部分答案)
    然后查询时散的暴力加上,取后缀差尝试更新答案即可

    Code

    //By Menteur_Hxy
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define F(i,a,b) for(register int i=(a);i<=(b);i++)
    using namespace std;
    
    int rd() {
    	int x=0,f=1; char c=getchar();
    	while(!isdigit(c)) {if(c=='-')f=-f; c=getchar();}
    	while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    	return x*f;
    }
    
    typedef long long LL;
    const int N=100010;
    int n,q,blo,top;
    LL da[N],cp[N],cnt[320][N],bl[N],f[320][N],num[N],sta[N];
    LL now,ans;
    
    int main() {
    	n=rd(),q=rd(); blo=sqrt(n);
    	F(i,1,n) cp[i]=da[i]=rd(),bl[i]=(i-1)/blo+1;
    	sort(cp+1,cp+1+n);//4
    	int u=unique(cp+1,cp+1+n)-cp-1;//1
    	F(i,1,n) da[i]=lower_bound(cp+1,cp+1+u,da[i])-cp;
    	F(i,1,bl[n]) {
    		now=0;
    		F(j,lower_bound(bl+1,bl+1+n,i)-bl,n)
    			cnt[i][da[j]]++,now=max(now,(LL)cnt[i][da[j]]*cp[da[j]]),f[i][j]=now;
    	}
    	while(q--) {
    		int a=rd(),b=rd(); ans=top=0;
    		if(bl[a]==bl[b]) {//5
    			F(i,a,b) num[da[i]]++,ans=max(ans,(LL)(num[da[i]]*cp[da[i]]));
    			printf("%lld
    ",ans);
    			F(i,a,b) num[da[i]]=0;
    			continue;
    		}
    		ans=f[bl[a]+1][b];
    		int tmp=lower_bound(bl+1,bl+1+n,bl[b])-bl;
    		F(i,tmp,b) num[da[i]]++,sta[++top]=da[i];
    		tmp=lower_bound(bl+1,bl+1+n,bl[a]+1)-bl-1;//2
    		F(i,a,tmp) {
    			num[da[i]]++; sta[++top]=da[i];
    			ans=max(ans,(LL)(cnt[bl[a]+1][da[i]]-cnt[bl[b]][da[i]]+num[da[i]])*cp[da[i]]);//3
    		}
    		F(i,1,top) num[sta[i]]=0; 
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
    版权声明:本文为博主原创文章,未经博主允许不得转载。 博主:https://www.cnblogs.com/Menteur-Hxy/
  • 相关阅读:
    关于group by【转载】
    Hive常用命令
    Hive学习笔记【转载】
    Java多线程的join()
    Java多线程编程
    把struts2-convention-plugin丢进太平洋
    关于unsigned int和int的加法
    C#高级参数out,ref,params
    Winform禁止程序多开 &&禁止多开且第二次激活第一次窗口
    .NET对象与Windows句柄(三):句柄泄露实例分析
  • 原文地址:https://www.cnblogs.com/Menteur-Hxy/p/9301361.html
Copyright © 2011-2022 走看看