zoukankan      html  css  js  c++  java
  • CF1146D Frequency Problem

    题目链接 Easy

    题目链接 Hard

    题意简述

    给定一个长度为 (n) 的数列 ({a_i}),满足 (1le a_ile n)

    求一个最长的子区间,使得这个子区间内出现次数最多的数不止一个。

    数据范围:(1le nle 2 imes10^5)

    对于简单版有 (1le a_ile 100)

    Solution

    看上去没办法用数据结构强行维护,考虑做一些转化。

    考虑长度为 (i) 的前缀,设这个前缀存在唯一出现次数最多的数为 (x),令左端点 (j) 初始为 (1)

    在左端点 (j) 不断加 (1) 的过程中,维护 ([j,i]) 内每种数的出现次数,一旦当前存在一个 (y e x) 满足 (y)(x) 出现次数相等,就停止扫描,这时候可以用 (i-j+1) 更新答案。

    (s_{i,x,y}=sum_{j=1}^i[a_j=x]-sum_{j=1}^i[a_j=y]),则对于右端点 (i),出现次数最多的数为 (x),其最小合法左端点为:

    [1+min_{y e x}{ ext{minimum }j ext{ satisfying }s_{j,x,y}=s_{i,x,y}} ]

    即对于每种不为 (x) 的数 (y) 都考虑其第一次出现次数相等的位置取个最小值。

    于是可以枚举 (x)(y),注意到我们一定有 (a_{ ext{minimum }j ext{ satisfying }s_{j,x,y}=s_{i,x,y}}=x),故可以枚举所有 (a_i=x) 的位置 (i) 和所有满足 ([1,i]) 中出现次数最多的数为 (x) 的位置 (i) 来求出 ( ext{minimum }j ext{ satisfying }s_{j,x,y}=s_{i,x,y}),期间需要对每种 (s_{i,x,y}) 的出现位置记录一个数组,并且需要一些特殊技巧来达到 (O(n)) 的空间。

    这样可以过 Easy。对于 Hard,取 (S=lfloorsqrt n floor),把数分成出现次数 (le S)(>S) 两类,用上面的方法可以 (O(nS)) 求出所有满足最大出现次数 (>S) 的区间长度最大值。

    对于最大出现次数 (le S) 的区间,不难发现区间右端点和最大出现次数确定了之后,只需考虑最小的左端点,故这一部分外围枚举 (1le jle S) 表示最大出现次数,然后右端点 (i) 从小到大用 two-pointers 维护最小左端点即可,这一部分复杂度也是 (O(nS)),总复杂度 (O(nsqrt n))

    Code

    #include <bits/stdc++.h>
    
    template <class T>
    inline void read(T &res)
    {
    	res = 0; bool bo = 0; char c;
    	while (((c = getchar()) < '0' || c > '9') && c != '-');
    	if (c == '-') bo = 1; else res = c - 48;
    	while ((c = getchar()) >= '0' && c <= '9')
    		res = (res << 3) + (res << 1) + (c - 48);
    	if (bo) res = ~res + 1;
    }
    
    template <class T>
    inline T Max(const T &a, const T &b) {return a > b ? a : b;}
    
    template <class T>
    inline T Min(const T &a, const T &b) {return a < b ? a : b;}
    
    const int N = 2e5 + 5;
    
    int n, a[N], ans, cnt[N], ty[N], c[N], z[N], o[N], s[N], ToT, vis[N], fis[N],
    S, b[N], id[N], tot;
    std::vector<int> ot[N], occ[N];
    
    void inc(int c, int i, int &cur1, int &cur2, int delta)
    {
    	if (cnt[c] == i) cur1--; if (cnt[c] > i) cur2--;
    	cnt[c] += delta;
    	if (cnt[c] == i) cur1++; if (cnt[c] > i) cur2++;
    }
    
    int main()
    {
    	int cur = 0, x;
    	read(n); S = sqrt(n);
    	for (int i = 1; i <= n; i++) read(a[i]), b[a[i]]++;
    	for (int i = 1; i <= n; i++) if (b[i] > S) id[i] = ++tot;
    	for (int i = 1; i <= n; i++)
    	{
    		if ((++cnt[a[i]]) > cur) cur = cnt[a[i]], x = a[i];
    		else if (cnt[a[i]] == cur) x = -1;
    		ty[i] = x; c[i] = cur; o[i] = cnt[a[i]];
    		if (x == -1) ans = i;
    		if (id[a[i]]) ot[id[a[i]]].push_back(-i);
    		if (x > 0 && id[x]) ot[id[x]].push_back(i);
    	}
    	for (int i = 1; i <= n; i++) z[i] = n + 1;
    	for (int T = 1; T <= tot; T++)
    	{
    		for (int i = 1; i <= n; i++) s[i] = s[i - 1] + (id[a[i]] == T);
    		for (int D = 1; D <= tot; D++) if (D != T)
    		{
    			ToT++;
    			for (int i = 0; i < ot[D].size(); i++)
    				if (ot[D][i] < 0)
    				{
    					int tmp = o[-ot[D][i]] - s[-ot[D][i]];
    					if (tmp >= 0 && vis[tmp] < ToT)
    						vis[tmp] = ToT, fis[tmp] = -ot[D][i];
    				}
    				else
    				{
    					int tmp = c[ot[D][i]] - s[ot[D][i]];
    					if (vis[tmp] == ToT)
    						z[ot[D][i]] = Min(z[ot[D][i]], fis[tmp]);
    				}
    		}
    	}
    	for (int i = 1; i <= n; i++) ans = Max(ans, i - z[i]);
    	for (int T = 1; T <= S; T++)
    	{
    		memset(cnt, 0, sizeof(cnt));
    		for (int i = 1, j = 1, cur1 = 0, cur2 = 0; i <= n; i++)
    		{
    			inc(a[i], T, cur1, cur2, 1);
    			while (cur2) inc(a[j], T, cur1, cur2, -1), j++;
    			if (cur1 > 1) ans = Max(ans, i - j + 1);
    		}
    	}
    	return std::cout << ans << std::endl, 0;
    }
    
  • 相关阅读:
    二维码跳转不同的 app store
    HTML 保存图片到本地
    HTML5 的一些小的整理吧
    Echarts 3.19 制作常用的图形 非静态
    word2010设置页码起始位置及前后页码不同的方法
    经struts2中的action后,jsp中css失效的问题
    在Linux和Windows下配置MyEclipse+Tomcat+JDK的一些问题
    MyEclipse自动退出问题解决办法
    (转)java web建议学习路线
    Linux中MyEclipse+tomcat遇到的问题
  • 原文地址:https://www.cnblogs.com/xyz32768/p/14052798.html
Copyright © 2011-2022 走看看