求助站外题
  • 板块学术版
  • 楼主AAA404
  • 当前回复4
  • 已保存回复4
  • 发布时间2023/4/8 18:46
  • 上次更新2023/10/23 19:02:06
查看原帖
求助站外题
723198
AAA404楼主2023/4/8 18:46

题目描述

每次考试结束,老师总要把所有的同学的成绩进行排序,这还不够,老师总关心获得哪个分数的学生人数是最多的,请帮助老师完成这个任务。

输入格式

第一行包含两个整数n和m,分别代表n个同学,后续有m个询问。 第二行包含n个同学的成绩,这n个同学的成绩是一个整数,而且已经是从小到大排好序的。 接下来m行,每行包含两个整数l和r,表示老师需要了解第l个同学到第r个同学间(包含第l和第r个同学)得到同分的最多人数,针对每个询问,请输出最多人数。

输出格式

每行一个整数,表示对应区间的得到同分的最多人数

输入样例

10 3

2 2 6 6 6 6 8 10 10 10

2 3

1 10

5 10

输出样例

1

4

3

My Code

#include<bits/stdc++.h>
using namespace std;
int n,m,Log[100001],f[100001][31];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
inline int RMQ(int x,int y,int l)
{
	return max(f[x][l],f[y-(1<<l)+1][l]);
}
int main()
{
 //	freopen(".in","r",stdin);
 //	freopen(".out","w",stdout);
 	n=read(),m=read();
 	int la=114514;
	for(int i=1;i<=n;i++)
	{
		int x=read();
		if(x==la)f[i][0]=f[i-1][0]+1;
		else f[i][0]=1;
		la=x;
	} 
	Log[1]=0;
	for(int i=2;i<=n;i++)Log[i]=Log[i/2]+1;
	for(int j=1;j<=Log[n];j++)
	{
		for(int i=1;i<=n-(1<<j)+1;i++)
		{
			f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
		}
	}
	for(int i=1;i<=m;i++)
	{
		int x=read(),y=read();
		int l=Log[y-x+1];
		int maxx=RMQ(x,y,l);
		if(f[x][0]==1)printf("%d\n",maxx);
		else
		{
			if(f[x+maxx-f[x][0]][0]==maxx)printf("%d\n",max((maxx-f[x][0]+1),RMQ(x+maxx-f[x][0]+1,y,Log[y-(x+maxx-f[x][0])])));
			else printf("%d\n",maxx);
		}
	}
 	return 0;
}


ST表

自己的数据都没问题,样例也过了,交上去0分

思路大致是:

构造一个序列,例如样例构造成:1 2 1 2 3 4 1 1 2 3

然后针对每一次询问,先查区间最大值,然后看区间开头是不是1,如果是的话答案就一定是最大值(这里不是说一定和最大值是一段的,即使不是一段的,最大值也有一段完整的序列),如果不是就判断最大值与区间开头是不是一段的:

是的话比较这一段的长度和后面的区间最大值

不是的话直接输出最大值

2023/4/8 18:46
加载中...