【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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

bzoj4241: 历史研究

分块
  • FSAHFGSADHSAKNDAS
  • FSAHFGSADHSAKNDAS
  • 2017年05月05日 08:52
  • 441

BZOJ4241 历史研究

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

【bzoj4241】历史研究

这题也是坑了好久>_<   之前whx带我刷JOI的时候本来应该要做的。。。可是太懒没有写。。。   区间询问加权众数。 分块,预处理出块和块之间的答案,记录到第i个块数字x出现了多少次...
  • GEOTCBRL
  • GEOTCBRL
  • 2015年11月19日 15:43
  • 571

[bzoj4241]历史研究

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

【bzoj4241】历史研究 分块

PoPoQQQ大神的题解: http://blog.csdn.net/popoqqq/article/details/47809173 一开始自己想了一种莫队的方法,结果发现复杂度错了...
  • u012288458
  • u012288458
  • 2016年01月06日 13:59
  • 889

【bzoj4241】 历史研究

http://www.lydsy.com/JudgeOnline/problem.php?id=4241 (题目链接)看到题目就联想到了【bzoj2809】 Apio2012—dispatching。...
  • MashiroSky
  • MashiroSky
  • 2016年07月31日 21:22
  • 173

BZOJ4241 历史研究 莫队算法 堆

欢迎访问~原文出处——博客园-zhouzhendong&AK 去博客园看该题解   题目   Description IOI国历史研究的第一人——JOI教授,最近获...
  • zhouzhendongAK
  • zhouzhendongAK
  • 2017年08月02日 21:28
  • 175

Bzoj4241:历史研究:莫队算法

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

bzoj4241 历史研究 回滚莫队

题目大意: 有一个长度为n的序列。 有m个询问,每次询问l~r范围内每个数值乘以该数值出现次数的最大值。题目分析: 据说这题可以在线做?这题普通的莫队GG,因为不支持快速删除操作,但是支持快速加...
  • Todobe
  • Todobe
  • 2017年07月06日 15:27
  • 265

[bzoj4241]历史研究 回滚莫队

bzoj4241 历史研究 回滚莫队
  • qq_37321281
  • qq_37321281
  • 2017年07月25日 20:21
  • 97
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【bzoj4241】历史研究
举报原因:
原因补充:

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