列表

详情


NC50446. 与众不同

描述

A是某公司的CEO,每个月都会有员工把公司的盈利数据送给A,A是个与众不同的怪人,A不注重盈利还是亏本,而是喜欢研究「完美序列」:一段连续的序列满足序列中的数互不相同。
A想知道区间[L,R]之间最长的完美序列长度。

输入描述

第一行两个整数N,M,N表示连续N个月,编号为0到N-1,M表示询问的次数;
第二行N个整数,第i个数表示该公司第i个月的盈利值a_i
接下来M行每行两个整数L,R,表示A询问的区间。

输出描述

输出M行,每行一个整数对应询问区间内的完美序列的最长长度。

示例1

输入:

9 2
2 5 4 1 2 3 6 2 4
0 8
2 6

输出:

6
5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 237ms, 内存消耗: 29968K, 提交时间: 2020-01-29 20:54:57

#include <bits/stdc++.h>

using namespace std;

const int base = 1e6+10,maxn = 2e5+10;
int pre[base*4+100];
int st[maxn][25],a[maxn];

int solve(int l,int r)
{
	int k = log(r-l+1)/log(2);
	int ans = max(st[l][k],st[r-(1<<k)+1][k]);
	return ans;
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; i++)
	{
		int x;
		scanf("%d",&x);
		x += base;
		a[i] = max(a[i-1],pre[x]);
		st[i][0] = i - a[i];
		pre[x] = i;
	}
	
	for(int j = 1; (1<<j) <= n; j++)
	for(int i = 1; (i+(1<<j-1)) <= n; i++)
	st[i][j] = max(st[i][j-1],st[i+(1<<j-1)][j-1]);
	
	while(m--)
	{
		int l,r;
		scanf("%d%d",&l,&r);
		++l,++r;
		if(a[r] < l)
		{
			printf("%d\n",r-l+1);
			continue;
		}
		int p = lower_bound(a+1,a+1+n,l-1) - a;
		int ans = max(p-l,solve(p,r));
		printf("%d\n",ans);
	}
 } 

C++11(clang++ 3.9) 解法, 执行用时: 275ms, 内存消耗: 29664K, 提交时间: 2020-05-30 12:12:40

#include<bits/stdc++.h>
using namespace std;
const int base=1e6+10,maxn=2e5+10;
int pre[base*4+100];
int st[maxn][25],a[maxn];
int solve(int l,int r)
{
	int k=log(r-l+1)/log(2);
	int ans=max(st[l][k],st[r-(1<<k)+1][k]);
	return ans;
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		x+=base;
		a[i]=max(a[i-1],pre[x]);
		st[i][0]=i-a[i];
		pre[x]=i; 
	}
	for(int j=1;(1<<j)<=n;j++)
	for(int i=1;(i+(1<<j-1))<=n;i++)
	st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
	while(m--)
	{
		int l,r;
		scanf("%d%d",&l,&r);
		++l,++r;
		if(a[r]<l)
		{
			printf("%d\n",r-l+1);
			continue;
		}
		int p=lower_bound(a+1,a+1+n,l-1)-a;
		int ans=max(p-l,solve(p,r));
		printf("%d\n",ans);
	}
}

上一题