zoukankan      html  css  js  c++  java
  • BZOJ 4241 历史研究

    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)
     

      这道题刚开始时没有思路......后来发现好像和区间众数的方法有点像......

      好了,我们考虑如何做这道题。首先,我们可以把区间分块。然后,我们可以用$O(n sqrt{n})$的复杂度求出$f_{i,j}$,表示取第$i$块到第$j$块中所有元素的答案。

      然后,我们考虑如何得到区间$[l,r]$的答案。如果$l$和$r$在同一块,那么显然扫一遍这个块就可以了。否则,我们可以先把$[l,r]$覆盖的完整的块的答案统计一下,再统计一下边角余料中答案最大的数。显然答案一定在这三者中。

      但是,统计边角余料的答案并不好做。于是,我们可以再来一个数组$cnt_{i,j}$,表示前$i$个块中第$j$号元素出现了多少次(注意先要离散化),然后我们就可以$O(1)$地统计完整的块中每种元素出现的个数了。取一下$max$就可以了。

      下面是代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     7 #define maxn 100010
     8 #define kuai 501
     9 
    10 using namespace std;
    11 typedef long long llg;
    12 
    13 int n,m,N,ln,L[kuai],R[kuai],cnt[kuai][maxn];
    14 int a[maxn],b[maxn],lb,c[maxn],ci[maxn],be[maxn];
    15 llg f[kuai][kuai],ans;
    16 
    17 int getint(){
    18     int w=0;bool q=0;
    19     char c=getchar();
    20     while((c>'9'||c<'0')&&c!='-') c=getchar();
    21     if(c=='-') q=1,c=getchar();
    22     while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    23     return q?-w:w;
    24 }
    25 
    26 int main(){
    27     n=getint();m=getint();
    28     for(int i=1;i<=n;i++) a[i]=b[i]=getint();
    29     sort(b+1,b+n+1); lb=unique(b+1,b+n+1)-b-1;
    30     for(int i=1;i<=n;i++){
    31         int l=1,r=lb,mid;
    32         while(l!=r){
    33             mid=l+r>>1;
    34             if(a[i]<=b[mid]) r=mid;
    35             else l=mid+1;
    36         }
    37         c[i]=l;
    38     }
    39     N=sqrt(n); ln=n/N; if(n%N) ln++;
    40     for(int i=1;i<ln;i++) L[i]=R[i-1]+1,R[i]=N*i;
    41     L[ln]=R[ln-1]+1; R[ln]=n;
    42     for(int i=1,r;i<=ln;i++){
    43         ans=0; r=L[i]-1;
    44         for(int j=L[i];j<=R[i];j++) cnt[i][c[j]]++,be[j]=i;
    45         for(int j=1;j<=ln;j++){
    46             while(r<R[j]){
    47                 r++; ci[c[r]]++;
    48                 ans=max(ans,(llg)(ci[c[r]])*(llg)a[r]);
    49             }
    50             f[i][j]=ans;
    51         }
    52         for(int j=1;j<=n;j++) cnt[i][j]+=cnt[i-1][j];
    53         for(int j=1;j<=lb;j++) ci[j]=0;
    54     }
    55     while(m--){
    56         int l=getint(),r=getint(); ans=0;
    57         if(be[l]==be[r]){
    58             for(int i=l;i<=r;i++)
    59                 ans=max(ans,(llg)(++ci[c[i]])*(llg)a[i]);
    60             for(int i=l;i<=r;i++) ci[c[i]]--;
    61         }
    62         else{
    63             ans=f[be[l]+1][be[r]-1];
    64             for(int i=l;i<=R[be[l]];i++)
    65                 ans=max(ans,(llg)((++ci[c[i]])+cnt[be[r]-1][c[i]]-cnt[be[l]][c[i]])*(llg)a[i]);
    66             for(int i=L[be[r]];i<=r;i++)
    67                 ans=max(ans,(llg)((++ci[c[i]])+cnt[be[r]-1][c[i]]-cnt[be[l]][c[i]])*(llg)a[i]);
    68             for(int i=l;i<=R[be[l]];i++) ci[c[i]]--;
    69             for(int i=L[be[r]];i<=r;i++) ci[c[i]]--;
    70         }
    71         printf("%lld
    ",ans);
    72     }
    73     return 0;
    74 }
  • 相关阅读:
    ERROR 1045 (28000): Access denied for user 'xxx'@'localhost' (using password: YES)
    --skip-grant-tables命令
    mysql之mysql_config_editor
    Mysql8报错:ERROR 1227 (42000): Access denied; you need (at least one of) the SYSTEM_USER privilege(s) for this operation
    创建仅有查询指定表权限的用户
    centos7修改分辨率
    CreateProcess简单示例
    光标在Edit控件中的位置
    设计模式:原型模式(C++)【克隆羊多莉】
    设计模式2:策略模式工厂
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/5721562.html
Copyright © 2011-2022 走看看