给出 n 个整数 \(x_1, x_2, ...,x_n\) ,询问 [l, r] 中 max{\(x_k\times cnt_{x_k}\)}( \(cnt_i\) 表示 i 出现的次数)

Luogu

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

AtCoder

分析

回滚莫队裸题。

当然也可以用分块做,但我一开始打的分块,成功的只过了 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);
    }
}

我的错误分块代码

Code

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄