给出 n 个整数 \(x_1, x_2, ...,x_n\) ,询问 [l, r] 中 max{\(x_k\times cnt_{x_k}\)}( \(cnt_i\) 表示 i 出现的次数)
分析
回滚莫队裸题。
当然也可以用分块做,但我一开始打的分块,成功的只过了 4 个点......没调出来......
顺便贴一下官方题解,虽然是日文
代码
回滚莫队
//=========================
// author:hliwen
// date:2020.1.17
//=========================
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100005
#define il inline
#define re register
#define DEBUG puts("ok")
#define tie0 cin.tie(0),cout.tie(0)
#define fastio ios::sync_with_stdio(false)
#define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
typedef long long ll;
template <typename T> inline void read(T &x) {
T f = 1; x = 0; char c;
for (c = getchar(); !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
x *= f;
}
int n, m, q, sz;
int bl[N], L[N], R[N], id[N], cnt[N], tot[N];
ll t[N], hs[N], ans[N];
struct query {
int l, r, id;
friend bool operator < (query x, query y) {
return (bl[x.l] ^ bl[y.l]) ? bl[x.l] < bl[y.l] : x.r < y.r;
}
} qy[N];
int main() {
read(n), read(q);
sz = sqrt(n);
for (int i = 1; i <= n; ++i) {
read(t[i]), hs[i] = t[i];
bl[i] = (i - 1) / sz + 1;
}
m = bl[n];
for (int i = 1; i <= m; ++i) {
L[i] = (i - 1) * sz + 1;
R[i] = i * sz;
}
sort(hs + 1, hs + 1 + n);
int num = unique(hs + 1, hs + 1 + n) - hs - 1;
for (int i = 1; i <= n; ++i)
id[i] = lower_bound(hs + 1, hs + 1 + num, t[i]) - hs;
for (int i = 1; i <= q; ++i) {
read(qy[i].l), read(qy[i].r);
qy[i].id = i;
}
sort(qy + 1, qy + 1 + q);
int i = 1;
for (int k = 0; k <= m; ++k) {
int l = R[k] + 1, r = R[k];
ll now = 0;
memset(cnt, 0, sizeof cnt);
for ( ; bl[qy[i].l] == k; ++i) {
int ql = qy[i].l, qr =qy[i].r;
ll tmp = 0;
if (bl[ql] == bl[qr]) {
for (int j = ql; j <= qr; ++j) tot[id[j]] = 0;
for (int j = ql; j <= qr; ++j) {
++tot[id[j]];
tmp = max(tmp, 1ll * tot[id[j]] * t[j]);
}
ans[qy[i].id] = tmp;
}
else {
while (r < qr) {
++cnt[id[++r]];
now = max(now, 1ll * cnt[id[r]] * t[r]);
}
tmp = now;
while (l > ql) {
++cnt[id[--l]];
now = max(now, 1ll * cnt[id[l]] * t[l]);
}
ans[qy[i].id] = now;
while (l < R[k] + 1) --cnt[id[l++]];
now = tmp;
}
}
}
for (int i = 1; i <= q; ++i) printf("%lld\n", ans[i]);
return 0;
}
官方正解
#include<stdio.h>
#include<vector>
#include<algorithm>
#define SQ 100
/*
bucket size: 100
*/
using namespace std;
int c[110000];
int d[110000];
int z[110000];
vector<int>v[110000];
long long e[110000];
long long f[3000][3000];
int main(){
int a,b;
scanf("%d%d",&a,&b);
for(int i=0;i<a;i++)scanf("%d",c+i);
for(int i=0;i<a;i++){
z[i]=c[i];
}
std::sort(z,z+a);
for(int i=0;i<a;i++){
d[i]=lower_bound(z,z+a,c[i])-z;
v[d[i]].push_back(i);
}
for(int i=0;i<a/SQ;i++){
for(int j=0;j<a;j++)e[j]=0LL;
long long val=0LL;
for(int j=i*SQ;j<=a;j++){
if(j%SQ==0){
f[i][j/SQ]=val;
}
e[d[j]]+=z[d[j]];
val=max(val,e[d[j]]);
}
}
for(int i=0;i<b;i++){
int p,q;
scanf("%d%d",&p,&q);
p--;
long long ret=f[(p+SQ-1)/SQ][q/SQ];
for(int j=p;j%SQ;j++){
ret=max(ret,(long long)z[d[j]]*(lower_bound(v[d[j]].begin(),v[d[j]].end(),q)-lower_bound(v[d[j]].begin(),v[d[j]].end(),p)));
}
for(int j=q-1;(j+1)%SQ;j--){
ret=max(ret,(long long)z[d[j]]*(lower_bound(v[d[j]].begin(),v[d[j]].end(),q)-lower_bound(v[d[j]].begin(),v[d[j]].end(),p)));
}
printf("%lld\n",ret);
}
}
我的错误分块代码
原文地址:https://www.cnblogs.com/hlw1/p/12207564.html
时间: 2024-10-01 05:50:36