首页 > 其他分享 >P5048 [Ynoi2019 模拟赛] 题解

P5048 [Ynoi2019 模拟赛] 题解

时间:2023-12-11 12:34:03浏览次数:35  
标签:Ynoi2019 return P5048 int 题解 nowans len MAXN inline

题意

给定 \(n\) 个数,有 \(m\) 个询问,每个询问给定 \(l\) 和 \(r\),求出区间 \(l\) 到 \(r\) 中的最小众数出现次数,强制在线。

数据范围:\(n\le 500000\),空间限制:\(62.5MB\)。

思路

这道题的弱化版是 蒲公英,这道题加强的地方在于数据范围。正常的分块求区间众数的空间复杂度是 \(O(n\sqrt n)\) 的,这道题显然会 \(MLE\),于是考虑优化空间。

我们可以记录一个 \(vector\) 数组 \(v_{i}\) 表示值为 \(i\) 的所有数分别在原数组中的下标是多少,升序排列。再记录一个 \(s_{i}\) 表示在原数组中下标为 \(i\) 的数在它对应的 \(v_{s_{i}}\) 中的位置。在查询的时候先将 \(ans\) 赋值为中间所有整块的众数出现次数,再暴力枚举非整块。对于每一个数只需要判断当前数能否在 \(l\) 到 \(r\) 中出现 \(ans+1\) 次,即 \(a_{i}\) 在原数组出现 \(s_{i}\pm ans\) 次时是否小于 \(r\) 或者大于 \(l\),如果满足条件的话答案加一。

Code

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f
#define inf_db 127
#define ls id << 1
#define rs id << 1 | 1
#define re register
#define endl '\n'
typedef pair <int,int> pii;
const int MAXN = 2e5 + 1,MAXM = 5e2 + 1;
int n,m,len,num,t[MAXN],c,nowans,s[MAXN];
int p[MAXM][MAXM],a[MAXN],tmp[MAXN],l,r,lastans;
vector <int> v[MAXN];
inline bool cmp(int x,int y){return x < y;}
inline int Getpos(int x){return (x % len ? x / len + 1 : x / len);}
inline int Getlid(int x){return (x - 1) * len + 1;}
inline int Getrid(int x){return min(n,x * len);}
inline void Init()
{
	for(re int i = 1;i <= n;++i) tmp[i] = a[i];
	sort(tmp + 1,tmp + n + 1,cmp);
	c = unique(tmp + 1,tmp + n + 1) - tmp - 1;
	for(re int i = 1;i <= n;++i) a[i] = lower_bound(tmp + 1,tmp + c + 1,a[i]) - tmp;
	for(re int i = 1;i <= n;++i) v[a[i]].push_back(i),s[i] = v[a[i]].size() - 1;
	len = sqrt(n);num = ceil(1.0 * n / len);
	for(re int i = 1;i <= num;++i)
	{
		for(re int j = 1;j <= c;j++) t[j] = 0;
		nowans = 0;
		for(re int j = i;j <= num;++j)
			for(re int k = Getlid(j);k <= Getrid(j);++k)
			{
				t[a[k]]++;
				if(t[a[k]] > t[nowans]) nowans = a[k];
				if(t[a[k]] == t[nowans] && a[k] < nowans) nowans = a[k];
				p[i][j] = t[nowans];
			}
	}
}
inline int Ask(int l,int r)
{
	nowans = 0;
	int ct = 0,L = Getpos(l),R = Getpos(r);
	int Lid = Getlid(R),Rid = Getrid(L);
	if(L == R)
	{
		for(re int i = l;i <= r;++i) t[a[i]] = 0;
		for(re int i = l;i <= r;++i)
		{
			t[a[i]]++;
			if(a[i] == nowans) ct++;
			if(t[a[i]] > t[nowans]) nowans = a[i],ct = t[nowans];
			if(t[a[i]] == t[nowans] && a[i] < nowans) nowans = a[i],ct = t[nowans];
		}
		return t[nowans];
	}
	nowans = p[L + 1][R - 1];
	for(re int i = l;i <= Rid;++i) 
	{
		int length = v[a[i]].size();
		while(nowans + s[i] < length && v[a[i]][nowans + s[i]] <= r) nowans++;
	}
	for(re int i = Lid;i <= r;++i) while(s[i] - nowans >= 0 && v[a[i]][s[i] - nowans] >= l) nowans++;
	return nowans;
}
signed main()
{
	scanf("%d%d",&n,&m);
	for(re int i = 1;i <= n;++i) scanf("%d",&a[i]);
	Init();
	for(re int i = 1;i <= m;++i) 
	{
		scanf("%d%d",&l,&r);
		printf("%d\n",-Ask(l,r));
	}
	return 0;
}

标签:Ynoi2019,return,P5048,int,题解,nowans,len,MAXN,inline
From: https://www.cnblogs.com/Creeperl/p/17894119.html

相关文章

  • CF1842E Tenzing and Triangle 题解
    题意不多赘述。思路如果两个所选的三角形有重合部分的话,那么这种情况肯定是不会出现的。因为如果把这两个三角形合成一个大三角形的话,不仅覆盖面积会增大,而且花费的代价还不会多。于是我们可以想到用dp来解决,设\(dp_{i}\)表示删完横坐标为\(0\)到\(i\)中的点的最小代价......
  • [ABC304Ex] Constrained Topological Sort 题解
    题意给定一张有向图\(G\),有\(n\)个点和\(m\)条边,问是否存在一种拓扑序的排列\(P\)使得\(l_{i}\lep_{i}\ler_{i}\)。思路首先对于一条边\(u\tov\),如果限制满足\(r_{v}\ler_{u}\)或者\(l_{v}\gel_{u}\)的话,那么这个限制其实是不完全正确的。因为最终的序列......
  • 【题解】AtCoder abc322_f Random Update Query
    传送门:https://atcoder.jp/contests/abc332/tasks/abc332_f容易发现,对于一个位置$i$,$A_i$的最终值是由对$i$的最后一次赋值操作决定的;因此,将所有操作按时间顺序倒过来考虑,则由第$j$次操作决定$A_i$最终值的概率为"在第$(j+1)$~$m$次操作中没有修改过$i$的概率"与"第......
  • 【题解】AtCoder abc332_g Not Too Many Balls
    传送门:https://atcoder.jp/contests/abc332/tasks/abc332_g看完题,第一眼反应为最大流。建模方式为:以颜色为左部点,盒子为右部点,源点$S$向颜色$i$连一条容量为$A_i$的边,盒子$j$向汇点$T$连一条容量为$B_j$的边,颜色$i$向盒子$j$连一条容量为$ij$的边;在这张图......
  • AT_cf17_final_j Tree MST 题解
    题意:给定一颗\(n\)个点的树,点\(i\)有权值\(a_{i}\),边有边权。现在有另外一个完全图,两点之间的边权为树上两点之间的距离加上树上两点的点权,求这张完全图的最小生成树。首先有一个很显然的暴力,把完全图中每两点之间的边权算出来,然后跑一边最小生成树,时间复杂度\(O(n^{2}\lo......
  • P7735 [NOI2021] 轻重边 题解
    是一道树剖好题,之前听lsl讲过一点,于是很快就做出来了。题意:有一个\(n\)个节点的树,最开始的时候所有边都是轻边,维护两个操作:操作一:将\(u\)到\(v\)的路径中经过的所有点的邻边变为轻边,再将这条路径上的边变为重边。操作二:求出\(u\)到\(v\)这条路径上有多少条重边......
  • 小程序建立用户与数据的联系问题解决方案
    在小程序中建立用户与数据的联系是一个常见的问题,在本文中提供了一个解决方案。这个解决方案包括几个关键步骤。首先,需要通过用户登录功能实现用户的身份识别,并获取到用户的唯一标识符。接着,需要在后台数据库中创建一个用户表,用于存储用户的基本信息和与之相关联的数据。在这个表中......
  • ARC169 B Subsegments with Small Sums 题解
    LinkARC169BSubsegmentswithSmallSumsQuestion\(x\)是一个序列,定义\(f(x)\)为把序列\(x\)切成几段,每段的和不能超过\(S\)的最小段数给出序列\(A=(A_1,A_2,\cdots,A_N)\)求:\[\sum_{1\lel\leN}f((A_l,A_{l+1},\cdots,A_r))\]Question先考虑一个结论,\(x\)为......
  • P9915 「RiOI-03」3-2 题解
    更好的阅读这是一道找规律的题目。因为我个人习惯,以下部分使用从\(1\)开始的下标讲述。首先我们以\(1\)来说:发现在第\(x\)行\(y\)列的连通块是可以直接连到第\(1\)列的,所以很容易可以得出\(1\)到\(y\)列的连通块数量是\(2^y-1\)。接着,我们考虑再后面的情况:......
  • 常见问题解决 --- pip SSLEOFError
    问题C:\Users\Administrator\Desktop>pipinstallscapy-ihttp://pypi.douban.com/simple--trusted-hostpypi.douban.comLookinginindexes:http://pypi.douban.com/simpleWARNING:Retrying(Retry(total=4,connect=None,read=None,redirect=None,status=None......