zhr 隨機跳題跳到的,遂做之。
注意到 \(nk \le 5\times10^5\),考慮根號分治。
當 \(n\) 很大時,\(k\) 會很小,於是我們記錄每一行的字首和,每一次迴圈 \(k\) 個陣列的字首和取 \(\max\) 即可,時間複雜度 \(O(qk)\)。
當 \(k\) 很大時,\(n\) 會很小,我們暴力預處理區間 \([l,r]\) 的最大值,直接輸出即可,時間複雜度 \(O(n^2k+q)\)。
取閥值為 \(\sqrt n\) 的時候,可以在兩邊都達到最小值。
點選檢視程式碼
int n,k,q;
vector<int>a[maxn];
vector<int>pre[maxn];
const int lim=750;
int ans[lim+5][lim+5];
signed main() {
in3(n,k,q);
For(i,1,k) {
a[i].push_back(0);
pre[i].push_back(0);
For(j,1,n) {
int x;
in1(x);
a[i].push_back(x);
pre[i].push_back(x+pre[i][j-1]) ;
}
}
if(k<lim) {
For(i,1,q) {
int l,r;
in2(l,r);
int ans=-1e18;
For(j,1,k)
ans=max(ans,pre[j][r]-pre[j][l-1]);
cout<<ans<<'\n';
}
return 0;
}
For(i,1,n) For(j,1,n) ans[i][j]=-1e18;
For(i,1,k) {
For(j,1,n) {
int tot=0;
For(p,j,n) {
tot+=a[i][p];
ans[j][p]=max(ans[j][p],tot);
}
}
}
For(i,1,q) {
int l,r;
in2(l,r);
cout<<ans[l][r]<<'\n';
}
}