• LibreOJ #6285


    题目链接: #6285. 数列分块入门 9

    题目大意

    给出一个长为 (n) 的数列,以及 (n) 个操作,操作涉及询问区间的最小众数。

    solution

    一看这道题就两眼发昏两眼一抹黑抓瞎

    一看这道题就毫无思路,那我们怎么做呢

    我们仔细观察众数, 我们再看看我们用分块能分不到 (400)

    那我们就可以 (n * sqrt{n}) 预处理出任意两块之间的众数了

    那我们任意两块之间的众数处理完了, 这题就做的差不多了

    就差散块的处理方法, 我们散块可以直接处理, 暴力查找散块中是否有最优众数

    大约为 (n * sqrt{n} * 2)

    毕竟前有散块后也有散块

    但是有一些细节问题需要处理, 我们在计算个数的时候,会开一个桶,那我们就要离散化,然后在进行预处理

    还有我们在处理散块的时候要注意, 是不是只有一块,如果只有一块,我们就不要算重了

    Code:

    /**
    *    Author: Alieme
    *    Data: 2020.9.8
    *    Problem: LibreOJ #6285
    *    Time: O()
    */
    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <map>
    #include <vector>
    
    #define ll long long
    #define rr register
    
    #define inf 1e9
    #define MAXN 100010
    #define MAXM 6000
    
    using namespace std;
    
    inline int read() {
    	int s = 0, f = 0;
    	char ch = getchar();
    	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
    	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    	return f ? -s : s;
    }
    
    void print(int x) {
    	if (x < 0) putchar('-'), x = -x;
    	if (x > 9) print(x / 10);
    	putchar(x % 10 + 48);
    }
    
    int n, len, tot;
    
    int a[MAXN], id[MAXN], name[MAXN], c[MAXN];
    
    int f[MAXM][MAXM];
    
    map<int, int> b;
    
    vector<int> v[MAXN];
    
    bool vis[MAXN];
    
    inline void init(int x) {
    	int num = 0, maxx = 0;
    	memset(c, 0, sizeof c);
    	for (rr int i = (x - 1) * len + 1; i <= n; i++) {
    		c[a[i]]++;
    		if (c[a[i]] > num || (c[a[i]] == num && name[a[i]] < name[maxx])) num = c[a[i]], maxx = a[i];
    		f[x][id[i]] = maxx;
    	}
    }
    
    inline int get(int l, int r, int x) {return upper_bound(v[x].begin(), v[x].end(), r) - lower_bound(v[x].begin(), v[x].end(), l);}
    
    inline int query(int l, int r) {
    	int maxx = f[id[l] + 1][id[r] - 1], num = 0;
    	memset(vis, 0, sizeof vis);
    	num = get(l, r, maxx);
    	vis[maxx] = 1;
    	for (rr int i = l; i <= min(id[l] * len, r); i++) {
    		if (vis[a[i]]) continue;
    		vis[a[i]] = 1;
    		int res = get(l, r, a[i]);
    		if (res > num || (res == num && name[a[i]] < name[maxx])) num = res, maxx = a[i];
    	}
    	if (id[l] == id[r]) return name[maxx];
    	for (rr int i = (id[r] - 1) * len + 1; i <= r; i++) {
    		if (vis[a[i]]) continue;
    		vis[a[i]] = 1;
    		int res = get(l, r, a[i]);
    		if (res > num || (res == num && name[a[i]] < name[maxx])) num = res, maxx = a[i];
    	}
    	return name[maxx];
    }
    
    signed main() {
    	n = read();
    	len = sqrt(n);
    	for (rr int i = 1; i <= n; i++) {
    		a[i] = read(), id[i] = (i - 1) / len + 1;
    		if (b[a[i]] == 0) {
    			b[a[i]] = ++tot;
    			name[tot] = a[i];
    		}
    		a[i] = b[a[i]];
    		v[a[i]].push_back(i);
    	}
    	for (rr int i = 1; i <= n / len + 1; i++) init(i);
    	for (rr int i = 1; i <= n; i++) {
    		int l = read(), r = read();
    		cout << query(l, r) << "
    ";
    	}
    }
    
  • 相关阅读:
    override new virtual 的比较
    c#页面无内容解决方案
    插入排序
    排序算法(转)
    treenode遍历文件夹
    案例篇(1)
    索引器(转)
    迭代器的实现
    抽象类和接口的区别
    索引器与迭代器,属性的区别
  • 原文地址:https://www.cnblogs.com/lieberdq/p/13641837.html
Copyright © 2020-2023  润新知