题解 P8572【[JRKSJ R6] Eltaw】

Link

题意

给你 k 个长为 n 的序列 a1k,1n,有 q 次询问,每次询问给出一个区间 [l,r],求出所有序列中区间 [l,r] 的和的最大值。

1n,k,q5×1051n×k5×105

思路

暴力题。

先给出做法,对于一次询问的区间 [l,r],如果之前询问过,直接输出之前记录的答案,否则直接 O(k) 求出每个序列的区间和,求最大值并记录即可。

我们来分析复杂度,令 s=nk

考虑到 n,k 中必然有一个小于等于 s,分类讨论:

  1. nkns 时:

    询问的区间只有 O(n2) 种,每种需要 O(k) 的时间求出,则时间复杂度为 O(n2k),即为 O(ss)

  2. knks 时:

    最坏的情况是每次询问都要 O(k) 回答,此时也只需 O(qk)O(qs) 的时间回答。

综上,我们可以在 O(ss+q)O(s+qs) 的时间内解决本问题。

不希望被叫做根号分治。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
namespace IO{//by cyffff

}
const int N=5e5+10;
int n,k,q,a[N];
ll pr[N];
map<ll,ll>ans; 
int main(){
    n=read(),k=read(),q=read();
    for(int i=1;i<=k;i++){
        int p=(i-1)*n;
        for(int j=1;j<=n;j++)
            a[++p]=read();
        p=(i-1)*n+1;
        pr[p]=a[p];
        for(int j=2;j<=n;j++)
            p++,pr[p]=pr[p-1]+a[p];
    }
    while(q--){
        ll l=read(),r=read();
        if(ans.find(l*n+r)!=ans.end()) write(ans[l*n+r]),putc('\n');
        else{
            ll tmp=0;
            for(int i=1;i<=k;i++){
                int p=(i-1)*n;
                if(l!=1) tmp=max(tmp,pr[p+r]-pr[p+l-1]);
                else tmp=max(tmp,pr[p+r]);
            }
            write(ans[l*n+r]=tmp),putc('\n');
        }
    }
    flush();
}

再见 qwq~

posted @   ffffyc  阅读(11)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示