【bzoj4241】历史研究

原创 2015年11月19日 15:43:52

  这题也是坑了好久>_<
  之前whx带我刷JOI的时候本来应该要做的。。。可是太懒没有写。。。
  区间询问加权众数。
分块,预处理出块和块之间的答案,记录到第i个块数字x出现了多少次。然后查询的时候和普通众数基本一样,就是乘了个权值而已。
要离散化。
时间复杂度O(nlogn+mn)
昨晚写的常数太烂了。。。用了struct,数组开大了,狂M
然后卡了卡空间,狂RE doge
然后查了很久发现有个边界写的有点问题
改完之后就无限TLE辣QAQ
电脑课花了20min来rewrite结果就A掉了smg。。。。

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a,_=b;i<=_;i++)
#define per(i,a,b) for(int i=a,_=b;i>=_;i--)
#define maxn 100007
#define maxb 331

inline int rd() {
    char c = getchar();
    while (!isdigit(c)) c = getchar() ; int x = c - '0';
    while (isdigit(c = getchar())) x = x * 10 + c - '0';
    return x;
}

typedef long long ll;

inline void upmax(ll&a , ll b) { if (a < b) a = b ; }

typedef int arr_int[maxn];
typedef ll  arr_ll [maxn];
typedef int blk_int[maxb];
typedef ll  blk_ll [maxb];

int n , m , all , len , tot;
arr_int h , a , cnt , belong;
blk_ll  ans[maxb];
arr_int sum[maxb] , st , ed;

void input() {
    n = rd() , m = rd();
    rep (i , 1 , n) h[i] = a[i] = rd();
    sort(h + 1 , h + n + 1);
    all = unique(h + 1 , h + n + 1) - h - 1;
    rep (i , 1 , n) a[i] = lower_bound(h + 1 , h + all + 1 , a[i]) - h;
}

void init_block() {
    len = (int) sqrt(n + 0.5);
    rep (i , 1 , n)
        belong[i] = (i - 1) / len + 1;
    tot = belong[n];
    rep (i , 1 , tot)
        st[i] = (i - 1) * len + 1 , ed[i] = i * len;
    ed[tot] = n;
    rep (i , 1 , n)
        sum[belong[i]][a[i]] ++;
    rep (i , 1 , tot)
        rep(x , 1 , all)
            sum[i][x] += sum[i - 1][x];
    rep (i , 1 , tot) {
        rep (j , st[i] , n) cnt[a[j]] = 0;
        ll mx = 0;
        rep (j , st[i] , n) {
            int x = a[j];
            cnt[x] ++;
            upmax(mx , (ll) cnt[x] * h[x]);
            ans[i][belong[j]] = mx;
        }
    }
}

void query(int l , int r) {
    ll mx = 0;
    int L = belong[l] , R = belong[r];
    if (L == R) {
        rep (i , l , r) cnt[a[i]] ++ ;
        rep (i , l , r) {
            int x = a[i];
            if (!cnt[x]) continue;
            upmax(mx , (ll) cnt[x] * h[x]);
            cnt[x] = 0;
        }
    } else {
        if (L + 1 < R)
            mx = ans[L + 1][R - 1];
        rep (i , l , ed[L]) cnt[a[i]] ++ ;
        rep (i , st[R] , r) cnt[a[i]] ++ ;
        rep (i , l , ed[L]) {
            int x = a[i];
            if (!cnt[x]) continue;
            ll ts = sum[R - 1][x] - sum[L][x] + cnt[x];
            ts *= h[x] , cnt[x] = 0;
            upmax(mx , ts);
        }
        rep (i , st[R] , r) {
            int x = a[i];
            if (!cnt[x]) continue;
            ll ts = sum[R - 1][x] - sum[L][x] + cnt[x];
            ts *= h[x] , cnt[x] = 0;
            upmax(mx , ts);
        }
    }
    printf("%lld\n" , mx);
}

void solve() {
    init_block();
    memset(cnt , 0 , sizeof cnt);
    rep (i , 1 , m) {
        int l = rd() , r = rd();
        query(l , r);
    }
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("data.txt" , "r" , stdin);
        freopen("data.out" , "w" , stdout);
    #endif
    input();
    solve();
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

Manacher 模板 【bzoj2565】 最长双回文子串

Manacher是一种可以获得一个串以每一个位置为中心最长回文半径的算法。 它的主要思想就是利用已知的信息来减少获得新信息的不必要操作。 已知的信息就是已经求出的回文串,比如这张图,我们已知黑...
  • Todobe
  • Todobe
  • 2017年02月25日 21:11
  • 189

BZOJ4241 历史研究

一眼觉得是莫队,发现删除不是很好搞,于是上回滚莫队直接搞过 回滚莫队用于处理难以删除但是易于添加(其实易于删除难以添加也可以,但是没见过这样题-_-)的莫队,排序照常,如果左右端点在同一块直接暴力,这...

[BZOJ]4241 历史研究 回滚莫队

几句闲话 orz orz neither_nor(alone_wolf).上次他讲课的时候还没有去看他这道题,后来刷这道题的时候发现他用的是回滚莫队.这道题大多人几乎都用的是分块,...

BZOJ 4241 历史研究

莫队 或 分块莫队和分块都不难想到,分块做法可以支持在线。好久没写莫队了就写它吧。好气啊,本智障在莫队数组清零的if后面多打了一个分号,就这东西调了一个小时我会乱说?吃枣药丸。 更气的是昨天刚装的u...

[bzoj4241]历史研究

题目大意求区间加权众数。分块大法好显然我们可以用类似苹果树这道题的序列上问题的分块做法解决。 即初始化第i块到第j块的答案,以及每个元素在前i块出现的次数。 然后就很容易做了。#include #...

bzoj4241: 历史研究

分块

Bzoj4241:历史研究:莫队算法

题目链接:4241:历史研究 最近考莫队怎么考怎么挂……对莫队产生了一种莫名的感觉QAQ 于是我看见什么都觉得是莫队…… 这是病得治…… 比如说这道题,上来先写了一发莫队套线段树,时间复杂度直...

【bzoj4241】历史研究

4241: 历史研究 Time Limit: 80 Sec  Memory Limit: 512 MB Submit: 1181  Solved: 346 [Submit][Status][Di...

bzoj 4241: 历史研究 分块

题意给出n个数,每次询问一个区间最大的s(i)*i,s(i)为i这个数出现的次数。 n,m...

BZOJ4241 历史研究 (分块 回滚莫队-教程向)

题目大意给定一个长度为nn的序列,并提出qq个询问,每次询问要求回答区间 [l,r][l,r] 内所有的权值与其出现次数的积的最大值。题解看见这种xjb询问的题当然是要下意识地用分块来搞一搞的,又因为...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【bzoj4241】历史研究
举报原因:
原因补充:

(最多只允许输入30个字)