bzoj4241 历史研究

Posted 逢山开路 遇水架桥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4241 历史研究相关的知识,希望对你有一定的参考价值。

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4241

【题解】

和作诗相似。

f[i,j]表示块i到块j的答案。

g[i,j]表示1...i块中j出现次数。

那么分块直接做即可。

复杂度O(n根号n)

跑的好慢啊。。

技术分享
# include <vector>
# include <stdio.h>
# include <string.h>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 1e5 + 10, N = 360, BLOCK = 320;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, q, B;
int a[M], bl[M];
int bst[N], bnd[N];
vector<int> ps;
int t[M];
ll f[N][N];
int g[N][M];

inline void prepare(int x) {
    memset(t, 0, sizeof t);
    int tem = x;
    ll ans = 0;
    for (int i=bst[x]; i<=n; ++i) {
        ++t[a[i]];
        ans = max(ans, (ll)t[a[i]]*ps[a[i]-1]);
        if(i == bnd[tem]) {
            f[x][tem] = ans;
            ++tem;
        }
    }
}

int main() {
    scanf("%d%d", &n, &q);
    for (int i=1; i<=n; ++i) scanf("%d", a+i), ps.push_back(a[i]);
    sort(ps.begin(), ps.end());
    ps.erase(unique(ps.begin(), ps.end()), ps.end());
    for (int i=1; i<=n; ++i) a[i] = lower_bound(ps.begin(), ps.end(), a[i]) - ps.begin() + 1;
    for (int i=1; i<=n; ++i) bl[i] = (i-1)/BLOCK+1;
    B = bl[n];
    for (int i=1; i<=B; ++i) bst[i] = (i-1)*BLOCK+1, bnd[i] = min(n, i*BLOCK);
    for (int i=1; i<=B; ++i) prepare(i);
    for (int i=1; i<=B; ++i) {
        for (int j=1; j<=n; ++j) g[i][j] = g[i-1][j];
        for (int j=bst[i]; j<=bnd[i]; ++j) ++g[i][a[j]];
    }
    int l, r;
    while(q--) {
        scanf("%d%d", &l, &r);
        if(bl[l] == bl[r]) {
            ll ans = 0;
            for (int i=l; i<=r; ++i) t[a[i]] = 0;
            for (int i=l; i<=r; ++i) {
                ++t[a[i]];
                ans = max(ans, (ll)t[a[i]]*ps[a[i]-1]);
            }
            printf("%lld\n", ans);
            continue;
        }
        ll ans = 0;
        if(bl[r]-bl[l] != 1) ans = f[bl[l]+1][bl[r]-1];
        for (int i=l; i<=bnd[bl[l]]; ++i) t[a[i]] = g[bl[r]-1][a[i]] - g[bl[l]][a[i]];
        for (int i=bst[bl[r]]; i<=r; ++i) t[a[i]] = g[bl[r]-1][a[i]] - g[bl[l]][a[i]];
        
        for (int i=l; i<=bnd[bl[l]]; ++i) {
            ++t[a[i]];
            ans = max(ans, (ll)t[a[i]]*ps[a[i]-1]);
        }
        for (int i=bst[bl[r]]; i<=r; ++i) {
            ++t[a[i]];
            ans = max(ans, (ll)t[a[i]]*ps[a[i]-1]);
        }
        printf("%lld\n", ans);
    }
         
    return 0;
}
View Code

 

以上是关于bzoj4241 历史研究的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4241 历史研究

bzoj4241 历史研究

bzoj4241/AT1219 历史研究(回滚莫队)

[BZOJ4241]历史研究

[bzoj4241][历史研究] (分块)

BZOJ4241 历史研究 莫队算法 堆