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

    学回滚莫队的契机是昨晚上$gay$哥在$Loj$群里问区间莫队的做法,

    然后一位大爷提到回滚莫队这种东西,我感觉挺有意思的就学了一下……

    讲解

    看完就成回滚莫队板子题了QwQ

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #define N (100009)
     6 #define LL long long
     7 using namespace std;
     8 
     9 struct Que{int l,r,num; LL ans;}Q[N];
    10 int n,m,unit,pos=1;
    11 int a[N],b[N],v[N],ID[N],Keg[N];
    12 LL ans;
    13 
    14 bool cmp1(Que x,Que y) {return ID[x.l]==ID[y.l]?x.r<y.r:ID[x.l]<ID[y.l];}
    15 bool cmp2(Que x,Que y) {return x.num<y.num;}
    16 
    17 LL Calc(int l,int r)
    18 {
    19     LL ans=0;
    20     for (int i=l; i<=r; ++i) Keg[b[i]]=0;
    21     for (int i=l; i<=r; ++i)
    22         Keg[b[i]]++, ans=max(ans,(LL)Keg[b[i]]*a[i]);
    23     for (int i=l; i<=r; ++i) Keg[b[i]]=0;
    24     return ans;  
    25 }
    26 
    27 void Update(int x)
    28 {
    29     Keg[b[x]]++;
    30     ans=max(ans,(LL)Keg[b[x]]*a[x]);
    31 }
    32 
    33 void MoQueue(int num)
    34 {
    35     ans=0;
    36     for (int i=1; i<=n; ++i) Keg[i]=0;
    37     int L=min(unit*num,n);
    38     int l=L+1,r=L;
    39     while (ID[Q[pos].l]==num)
    40     {
    41         if (ID[Q[pos].l]==ID[Q[pos].r])
    42         {
    43             Q[pos].ans=Calc(Q[pos].l,Q[pos].r);
    44             ++pos; continue;
    45         }
    46         while (r<Q[pos].r) Update(++r);
    47         LL tmp=ans;
    48         while (l>Q[pos].l) Update(--l);
    49         Q[pos].ans=ans; ans=tmp;
    50         while (l<L+1) Keg[b[l]]--, l++;
    51         ++pos;
    52     }
    53 }
    54 
    55 int main()
    56 {
    57     scanf("%d%d",&n,&m);
    58     unit=sqrt(n);
    59     for (int i=1; i<=n; ++i)
    60         scanf("%d",&a[i]), v[i]=a[i];
    61     sort(v+1,v+n+1);
    62     int num=unique(v+1,v+n+1)-v-1;
    63     for (int i=1; i<=n; ++i)
    64         b[i]=lower_bound(v+1,v+num+1,a[i])-v;
    65         
    66     for (int i=1; i<=m; ++i)
    67         scanf("%d%d",&Q[i].l,&Q[i].r), Q[i].num=i;
    68     
    69     int cnt=n/unit+(n%unit!=0);
    70     for (int i=1; i<=n; ++i)
    71         ID[i]=(i-1)/unit+1;
    72     
    73     sort(Q+1,Q+m+1,cmp1);
    74     for (int i=1; i<=cnt; ++i)
    75         MoQueue(i);
    76     sort(Q+1,Q+m+1,cmp2);
    77     for (int i=1; i<=m; ++i)
    78         printf("%lld
    ",Q[i].ans);
    79 }
  • 相关阅读:
    android中ping命令的实现
    回溯法——求解0-1背包问题
    scanner使用中遇见的问题
    Eddy&#39;s digital Roots
    项目经理注意事项(3)---宏观把控
    Spring IOC容器
    C++对象模型——Template中的名称决议方式 (第七章)
    比赛对手名单
    猴子吃桃问题
    设计模式-单例模式(02)
  • 原文地址:https://www.cnblogs.com/refun/p/10106448.html
Copyright © 2011-2022 走看看