将回忆酿成烈酒入喉 从此不再挽留不再回头 |

Altwilio

园龄:3年5个月粉丝:10关注:7

LOJ数列分块 9 题解

1. 题意

给定一个长度 n 序列,每次查询区间 l,r 的众数。

2. 思路

如果边界是 [l,r]l 在第 a 块,r 在第 b 块,可以分成三个部分:

  1. la 最后一块
  2. [a+1b1]
  3. b 块到 r

根据上面的性质,如果我们预先处理 [a+1b1] 块的众数,再去遍历判断第一部分和第三部分是否有更合适的众数,这道题就能做出来了。

#include <map>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#pragma GCC optimize(3, "Ofast", "inline")
#pragma GCC optimize("no-stack-protector")
#define int long long
using namespace std;

template <class T> inline void read(T &x){
    x = 0; register char c = getchar(); register bool f = 0;
    while (!isdigit(c)) f ^= c == '-', c = getchar();
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
    if (f) x = -x;
}

template <class T> inline void print(T x){
    if (x < 0) putchar('-'), x = -x;
    if (x > 9) print(x / 10);
    putchar('0' + x % 10);
}

const int N = 2e5 + 10;
const int M = 1e3 + 10;
int n, b, tot, a[N], id[N], val[N], cnt[N], dp[M][M];
vector<int> block[N];
unordered_map<int,int> mp;

inline void init(int pos){
    memset(cnt, 0, sizeof cnt);
    int maxx = 0, ans = 0;
    for(int i = (pos - 1) * b + 1; i <= n; i ++){
        cnt[a[i]] ++;
        if(cnt[a[i]] > maxx || (cnt[a[i]] == maxx && val[a[i]] < val[ans])) ans = a[i], maxx = cnt[a[i]];
        dp[pos][id[i]] = ans;
    }
}

inline int getlen(int l, int r, int x){
    return upper_bound(block[x].begin(), block[x].end(), r) - lower_bound(block[x].begin(), block[x].end(), l);
}

int query(int l, int r){
    register int ans, maxx;
    ans = dp[id[l] + 1][id[r] - 1];
    maxx = getlen(l, r, ans);
    for(register int i = l; i <= min(id[l] * b, r); i++){
        int tmp = getlen(l, r, a[i]);
        if(tmp > maxx || (tmp == maxx && val[a[i]] < val[ans]))
            ans = a[i], maxx = tmp;
    }
    if(id[l] == id[r]) return ans;  
    for(register int i = (id[r] - 1) * b + 1; i <= r; i++){
        int tmp = getlen(l, r, a[i]);
        if(tmp > maxx || (tmp == maxx && val[a[i]] < val[ans]))
            ans = a[i], maxx = tmp;
    }
    return ans;
}

signed main(){
    read(n); b = 100;
    for(int i = 1; i <= n; i ++){
        read(a[i]);
        if(mp[a[i]] == 0) mp[a[i]] = ++ tot, val[tot] = a[i];
        a[i] = mp[a[i]];
        block[a[i]].push_back(i);
    }
    for(int i = 1; i <= n; i ++) id[i] = (i - 1) / b + 1;
    for(int i = 1; i <= id[n]; i ++) init(i);
    for(int i = 1, l, r; i <= n; i ++){
        read(l), read(r);
        print(val[query(l, r)]), puts("");
    }
    return 0;
}

本文作者:Altwilio

本文链接:https://www.cnblogs.com/William-Sg/p/16350978.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Altwilio  阅读(22)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起