日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ 4241: 历史研究

發布時間:2025/3/15 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ 4241: 历史研究 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Description

IOI國歷史研究的第一人——JOI教授,最近獲得了一份被認為是古代IOI國的住民寫下的日記。JOI教授為了通過這份日記來研究古代IOI國的生活,開始著手調查日記中記載的事件。
日記中記錄了連續N天發生的時間,大約每天發生一件。
事件有種類之分。第i天(1<=i<=N)發生的事件的種類用一個整數Xi表示,Xi越大,事件的規模就越大。
JOI教授決定用如下的方法分析這些日記:

  • 選擇日記中連續的一些天作為分析的時間段
  • 事件種類t的重要度為t*(這段時間內重要度為t的事件數)
  • 計算出所有事件種類的重要度,輸出其中的最大值
    現在你被要求制作一個幫助教授分析的程序,每次給出分析的區間,你需要輸出重要度的最大值。
    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)

    Source

    JOI 2013~2014 春季training合宿 競技1 By PoPoQQQ

    Solution

    • 題意 : 多次詢問區間中的 每個數*其出現次數 的最大值。

    • 我們可以離散化后做莫隊,但是普通莫隊是不可行的,因為刪去最大值我們并不知道次大值。

    • 這是我們需要稍作修改——回滾莫隊!

    • 同樣將詢問區間按左端點所屬塊為第一關鍵字、右端點為第二關鍵字從小到大排,

    • 每次我們將左指針置于塊的最右端,每次重新移動即可。

    • 若詢問的區間在同一塊內就 O(n)O(\sqrt n)O(n?) 暴力統計。

    • 總時間復雜度是 O(nn)O(n\sqrt n)O(nn?) 的。

    Code

    #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cctype> using namespace std; typedef long long LL; const int N=1e5+5; struct data {int l,r,id; }c[N]; LL sum; int a[N],b[N],bel[N],t[N],cnt[N]; LL ans[N]; inline int read() {int X=0,w=0; char ch=0;while(!isdigit(ch)) w|=ch=='-',ch=getchar();while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline bool cmp(data x,data y) {return bel[x.l]<bel[y.l] || bel[x.l]==bel[y.l] && x.r<y.r; } inline LL max(LL x,LL y) {return x>y?x:y; } inline int min(int x,int y) {return x<y?x:y; } inline void add(int x) {cnt[a[x]]++;sum=max(sum,(LL)cnt[a[x]]*b[a[x]]); } inline void del(int x) {cnt[a[x]]--; } int main() {int n=read(),q=read();int size=sqrt(n);for(int i=1;i<=n;i++){a[i]=b[i]=read();bel[i]=(i-1)/size+1;}sort(b+1,b+1+n);b[0]=unique(b+1,b+1+n)-(b+1);for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+b[0],a[i])-b;for(int i=1;i<=q;i++) c[i].l=read(),c[i].r=read(),c[i].id=i;sort(c+1,c+1+q,cmp);for(int i=1,j=1;i<=n;i+=size){sum=0;int up=min(n,i+size-1);int l=up+1,r=up;memset(cnt,0,sizeof(cnt));while(j<=q && bel[i]==bel[c[j].l]){if(bel[c[j].l]==bel[c[j].r]){LL val=0;for(int k=c[j].l;k<=c[j].r;k++) t[a[k]]=0;for(int k=c[j].l;k<=c[j].r;k++){t[a[k]]++;val=max(val,(LL)t[a[k]]*b[a[k]]);}ans[c[j].id]=val;j++;continue;}while(r<c[j].r) add(++r);LL val=sum;while(l>c[j].l) add(--l);ans[c[j].id]=sum;while(l<=up) del(l++);sum=val;j++;}}for(int i=1;i<=q;i++) printf("%lld\n",ans[i]);return 0; }

    總結

    以上是生活随笔為你收集整理的BZOJ 4241: 历史研究的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。