Luogu AT1219 歴史の研究___回滚莫队

题目大意:

长度为n的序列a,
定义区间内一个数的价值为 数值*出现次数,问区间内的数的最大价值是多少。
m个询问,每个询问给出 [ l , r ] [l,r] [l,r],问区间内数的最大价值。

1 < = n , m < = 1 0 5 , 1 < = a i < = 1 0 9 1<=n,m<=10^5,1<=a_i<=10^9 1<=n,m<=105,1<=ai<=109

分析:

引入一个大佬的博客:
Luogu AT1219 歴史の研究___回滚莫队_第1张图片
这题也是一个回滚莫队的裸题,直接上就完事了

代码:

#include 

#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)

#define N 100005

using namespace std;

typedef long long ll;

struct Node {
    int l, r, id;
}q[N];
int beln[N], sum[N], val[N], cdp[N], cnt[N], al[N], ar[N], d[N], n, m, siz, num;
ll ans[N];

void read(int &x) {
	int f = 1; x = 0; char s = getchar();
	while (s < '0' || s > '9') { if (s == '-') f = - 1; s = getchar(); }
	while (s >= '0' && s <= '9') { x = x * 10 + (s - '0'); s = getchar(); }
	x = x * f;
}

int cmp(Node aa, Node bb) {
    return (beln[aa.l] ^ beln[bb.l]) ? beln[aa.l] < beln[bb.l] : aa.r < bb.r; 
}

void write(ll x) {
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

int main() {
    read(n), read(m);
    siz = sqrt(n);
    num = (int)ceil((double)n / siz);
    rep(i, 1, num) {
	    al[i] = siz * (i - 1) + 1, ar[i] = siz * i;
        rep(j, al[i], ar[i]) beln[j]  = i;
    }
    ar[num] = n;
    rep(i, 1, n) read(val[i]), d[i] = val[i];
    sort(d + 1, d + n + 1);
    int tot = unique(d + 1, d + n + 1) - d - 1;
    rep(i, 1, n) cdp[i] = lower_bound(d + 1, d + tot + 1, val[i]) - d;
    rep(i, 1, m) read(q[i].l), read(q[i].r), q[i].id = i;
    sort(q + 1, q + m + 1, cmp);
    int i = 1;
    rep(k, 0, num) {
        int l = ar[k] + 1, r = ar[k];
        ll now = 0;
        memset(cnt, 0, sizeof(cnt));
        for (; beln[q[i].l] == k; i++) {
            int L = q[i].l, R = q[i].r;
            ll tmp = 0;
            if (beln[L] == beln[R]) {
                rep(j, L, R) sum[cdp[j]] = 0;
                rep(j, L, R) ++sum[cdp[j]], tmp = max(tmp, 1ll * sum[cdp[j]] * val[j]);
                ans[q[i].id] = tmp;
                continue;
            }
            while (r < R)  ++r, ++cnt[cdp[r]], now = max(now, 1ll * cnt[cdp[r]] * val[r]); 
            tmp = now;
			while (l > L)  --l, ++cnt[cdp[l]], now = max(now, 1ll * cnt[cdp[l]] * val[l]);  
            ans[q[i].id] = now;
            while (l < ar[k] + 1) --cnt[cdp[l]], ++l; 
            now = tmp;
        }
        if (i > m) break;
    }
    rep(i, 1, m) write(ans[i]), printf("\n");
    return 0;
}

你可能感兴趣的:(C++,莫队)