2523. 历史研究

题目链接

2523. 历史研究

IOI 国历史研究的第一人——JOI 教授,最近获得了一份被认为是古代 IOI 国的住民写下的日记。

JOI 教授为了通过这份日记来研究古代 IOI 国的生活,开始着手调查日记中记载的事件。

日记中记录了连续 N 天发生的时间,大约每天发生一件。

事件有种类之分。第 i(1iN) 发生的事件的种类用一个整数 Xi 表示,Xi 越大,事件的规模就越大。

JOI 教授决定用如下的方法分析这些日记:

  1. 选择日记中连续的一些天作为分析的时间段
  2. 事件种类 t 的重要度为 t× (这段时间内重要度为 t 的事件数)
  3. 计算出所有事件种类的重要度,输出其中的最大值

现在你被要求制作一个帮助教授分析的程序,每次给出分析的区间,你需要输出重要度的最大值。

输入格式

第一行两个空格分隔的整数 NQ,表示日记一共记录了 N 天,询问有 Q 次。

接下来一行 N 个空格分隔的整数 X1XNXi 表示第 i 天发生的事件的种类。

接下来 Q 行,第 i(1iQ) 有两个空格分隔整数 AiBi,表示第 i 次询问的区间为 [Ai,Bi]

输出格式

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

数据范围

1N105,
1Q105,
1Xi109

输入样例:

5 5 9 8 7 8 9 1 2 3 4 4 4 1 4 2 4

输出样例:

9 8 8 16 16

解题思路

回滚莫队

排序方式同普通莫队,即将 l 分块,每块内 r 递增,每块长度为 n,每次操作都是一块一块操作,先暴力处理块内的询问,每次其复杂度为 n,然后处理块间的询问,由于一个块内的 r 指针递增,即处理询问时 r 指针递增,而 l 不定,但 l 指针始终在块内,所以处理 l 指针可以暴力

  • 时间复杂度:O(nn)

代码

// Problem: 历史研究 // Contest: AcWing // URL: https://www.acwing.com/problem/content/2525/ // Memory Limit: 64 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1e5+5; int n,m,w[N],cnt[N],len; LL ans[N]; vector<int> nums; struct query { int id,l,r; }q[N]; int get(int x) { return x/len; } void add(int x,LL &res) { cnt[x]++; res=max(res,(LL)nums[x]*cnt[x]); } void del(int x) { cnt[x]--; } int main() { cin>>n>>m; for(int i=1;i<=n;i++)cin>>w[i],nums.pb(w[i]); sort(nums.begin(),nums.end()); nums.erase(unique(nums.begin(),nums.end()),nums.end()); for(int i=1;i<=n;i++)w[i]=lower_bound(nums.begin(),nums.end(),w[i])-nums.begin(); len=sqrt(n); for(int i=1;i<=m;i++) { q[i].id=i; cin>>q[i].l>>q[i].r; } sort(q+1,q+1+m,[](const query &a,const query &b){ int al=get(a.l),bl=get(b.l); if(al!=bl)return al<bl; return a.r<b.r; }); for(int x=1;x<=m;) { int y=x; while(y<=m&&get(q[y].l)==get(q[x].l))y++; int right=get(q[x].l)*len+len-1; while(x<y&&q[x].r<=right) { int l=q[x].l,r=q[x].r,id=q[x].id; LL res=0; for(int i=l;i<=r;i++)add(w[i],res); ans[id]=res; for(int i=l;i<=r;i++)del(w[i]); x++; } LL res=0; int i=right,j=right+1; while(x<y) { int l=q[x].l,r=q[x].r,id=q[x].id; while(i<r)add(w[++i],res); LL backup=res; while(j>l)add(w[--j],res); ans[id]=res; while(j<right+1)del(w[j++]); res=backup; x++; } memset(cnt,0,sizeof cnt); } for(int i=1;i<=m;i++)cout<<ans[i]<<'\n'; return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16768619.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示