信心题(莫队算法)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MMMMMMMW/article/details/81155759

N - 信心题

给定一个含有n个数字的数列,每个数字都有一个值a[i](下标从1开始)。定义第i个数字和第j个数字间的距离dis(i,j)=abs(i-j)。

接下来给出q个询问,每次询问一个区间[l,r],要求求出一对数字(i,j)(l<=i<=j<=r),使得a[i]=a[j]并且dis(i,j)最大,由于这样的数对可能有多个,因此答案只要输出dis。

Input

题目包含多组数据

每组数据第一行一个数n

第二行n个数字,表示数列a

第三行一个数字q,表示询问个数

接下来q行,每行两个数l,r,表示询问

N<=10^5

Q<=10^4

1<=a[i]<=10^3

1<=l<=r<=n

Output

每个询问输出一个数组dis

Sample Input

5
1 2 3 1 2
3
3 3
2 5
1 5

Sample Output

0
3
3

虽说是信心题,但还是比较麻烦的,这个用的算法是莫队算法,大体思路就是建立一个position[数字值][从左到右第几个] = 该值在给出数列的位置。

下面是代码:

#include <cstdio>  
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <stack>
#include <queue>
using namespace std;
#define ll long long
const int maxn = 1e5+5;
struct node
{
	int l,r,id;
}que[maxn];
vector<int> position[1005];//存放每个值的位置
int cur[maxn];
int l[maxn],r[maxn];
int ans[maxn];
int n,q,limit;
bool cmp(node a,node b)
{
	if(a.l/limit == b.l/limit)
		return a.r < b.r;
	return a.l < b.l;
}
int main()
{
	while(scanf("%d",&n) != EOF)
	{
		memset(l,-1,sizeof(l));
		memset(r,-1,sizeof(r));
		for(int i = 1;i <= 1000;i++)
			position[i].clear();
		for(int i = 1;i <= n;i++)
		{
			scanf("%d",&cur[i]);
			position[cur[i]].push_back(i);
		}
		scanf("%d",&q);
		for(int i = 1;i <= q;i++)
		{
			scanf("%d%d",&que[i].l,&que[i].r);
			que[i].id = i;
		}
		limit = (int)(sqrt(n)+0.5);
		sort(que+1,que+1+q,cmp);

		int L,R;
		L = R = 0;
		for(int i = 1;i <= q;i++)
		{
			while(L < que[i].l)
			{
				l[cur[L]]++;
				L++;
			}
			while(R > que[i].r)
			{
				r[cur[R]]--;
				R--;
			}
			while(L > que[i].l)
			{
				L--;
				l[cur[L]]--;
			}
			while(R < que[i].r)
			{
				R++;
				r[cur[R]]++;
			}

			int maxx = 0;
			for(int j = 1;j <= 1000;j++)
			{
				if(r[j] <= 0)
					continue;
				int l1 = position[j][l[j]+1];
				//上面为什么加1?举个例子很容易懂:
				//对于数列1 2 2 1,如果是区间[1,4],那么l[1] = -1,r[1] = 1
				int rr = position[j][r[j]];
				maxx = max(maxx,rr-l1);
			}
			ans[que[i].id] = maxx;
		}
		for(int i = 1;i <= q;i++)
			printf("%d\n", ans[i]);
	}
	//cout << "AC" <<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/MMMMMMMW/article/details/81155759
今日推荐