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;
}

时间: 2024-08-06 11:13:29

bzoj4241 历史研究的相关文章

BZOJ4241 历史研究 莫队算法 堆

欢迎访问~原文出处--博客园-zhouzhendong&AK 去博客园看该题解 题目 Description IOI国历史研究的第一人--JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. 日记中记录了连续N天发生的时间,大约每天发生一件. 事件有种类之分.第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大. JOI教授决定用如下的方法分析这些日记: 1.

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

Description IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. 日记中记录了连续N天发生的时间,大约每天发生一件. 事件有种类之分.第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大. JOI教授决定用如下的方法分析这些日记: 1. 选择日记中连续的一些天作为分析的时间段 2. 事件种类t的重要度为t*(这段时间内重要度为t

bzoj4241 历史研究——分块

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4241 就是分块,预处理出从第 i 块到 j 位置的答案,以及从第 i 块到最后位置间每个数出现的次数: 然后块内统计.块外暴力即可. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using na

bzoj 4241 历史研究

Description IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. 日记中记录了连续N天发生的时间,大约每天发生一件. 事件有种类之分.第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大. JOI教授决定用如下的方法分析这些日记: 1. 选择日记中连续的一些天作为分析的时间段 2. 事件种类t的重要度为t*(这段时间内重要度为t

【AT1219】历史研究

题面 题目描述 \(IOI\)国历史研究的第一人--\(JOI\)教授,最近获得了一份被认为是古代\(IOI\)国的住民写下的日记.\(JOI\)教授为了通过这份日记来研究古代\(IOI\)国的生活,开始着手调查日记中记载的事件. 日记中记录了连续\(N\)天发生的时间,大约每天发生一件. 事件有种类之分.第\(i\)天\((1<=i<=N)\)发生的事件的种类用一个整数\(X_i\)表示,\(X_i\)越大,事件的规模就越大. \(JOI\)教授决定用如下的方法分析这些日记: 选择日记中连续

【bzoj4241】 历史研究

http://www.lydsy.com/JudgeOnline/problem.php?id=4241 (题目链接) 看到题目就联想到了[bzoj2809] Apio2012—dispatching.想了想权值分块+莫队,发现不好维护块内最值,又看了看80s的时间,于是怒水一发线段树+莫队,结果先WA后TLE,不断TLE,无论怎么改常数都不行,难道nlogn*sqrt(n)就是过不了吗!!不爽,蒯个题解,再见! 题意:求区间加权众数. solution  貌似是分块,离散化之后,用mx[i][

习题:历史研究(回滚莫队)

题目 传送门 思路 很版的一道回滚莫队的题 我们如果用普通的莫队,我们发现最难维护的是最大值, 因为你无法预测缩减时最大值的变化,还要带一个线段树或者什么来维护 时间复杂度为\(O(n*log_n*\sqrt n)\) 但是我们想,我们如果已知一个莫队的左端点和右端点以及它的最大值 那么这个莫队向外拓展我们是很容易维护的 之后如果下一个操作也是向外拓展就向外拓展,如果是内缩, 我们就将这个莫队还原成为我们最开始已知的样子,在进行拓展 这也就是回滚莫队的主要思想,这道题也是如此 时间复杂度依然也是

AT1219 歴史の研究(回滚莫队)

题目描述 IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. 日记中记录了连续N天发生的时间,大约每天发生一件. 事件有种类之分.第i天(1<=i<=N)发生的事件的种类用一个整数Xi?表示,Xi?越大,事件的规模就越大. JOI教授决定用如下的方法分析这些日记: 选择日记中连续的一些天作为分析的时间段 事件种类t的重要度为t*(这段时间内重要度为t的事件数) 计算出所有

使用TCP时序图解释BBR拥塞控制算法的几个细节

周六,由于要赶一个月底的Deadline,因此选择了在家VPN加班,大半夜就爬起来跑用例,抓数据...自然也就没有时间写文章和外出耍了...不过利用周日的午夜时间(不要问我为什么可以连续24小时不睡觉,因为我觉得吃饭睡觉是负担),我决定把工作上的事情先放下,还是要把每周至少一文补上,这已经成了习惯.由于上周实在太忙乱,所以自然根本没有更多的时间去思考一些"与工作无关且深入"的东西,我指的与工作无关并非意味着与IT,与互联网无关,只是意味着不是目前我在做的.比如在两年前,VPN,PKI这