FZU 2226 信心题

Problem Description

给定一个含有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
离线,然后排序乱搞
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int maxn = 1e4 + 10;
int n, m, x, ans[maxn];
int L[maxn], R[maxn];
vector<int> p[maxn];

struct point
{
	int l, r, id;
	void read(int x) { id = x; scanf("%d%d", &l, &r); }
}q[maxn], q1[maxn], q2[maxn];

bool cmp1(const point &a, const point &b)
{
	return a.l < b.l;
}

bool cmp2(const point &a, const point &b)
{
	return a.r < b.r;
}

int main()
{
	while (scanf("%d", &n) != EOF)
	{
		for (int i = 1; i <= 1000; i++) p[i].clear();
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &x);
			p[x].push_back(i);
		}
		scanf("%d", &m);
		for (int i = 0; i < m; i++)
		{
			q[i].read(i);
			q1[i] = q2[i] = q[i];
			ans[i] = 0;
		}
		sort(q1, q1 + m, cmp1);
		sort(q2, q2 + m, cmp2);
		for (int i = 1; i <= 1000; i++)
		{
			if (!p[i].size()) continue;
			int k1 = 0, k2 = 0;
			for (int j = 0; j < p[i].size(); j++)
			{
				while (k1 < m && q1[k1].l <= p[i][j])
				{
					L[q1[k1++].id] = p[i][j];
				}
				while (k2 < m && q2[k2].r < p[i][j])
				{
					R[q2[k2++].id] = j ? p[i][j - 1] : 0;
				}
			}
			while (k1 < m) L[q1[k1++].id] = n + 1;
			while (k2 < m) R[q2[k2++].id] = p[i].size() ? p[i][p[i].size() - 1] : 0;
			for (int j = 0; j < m; j++)
			{
				if (L[j] >= q[j].l&&L[j] <= q[j].r)
				{
					if (R[j] >= q[j].l&&R[j] <= q[j].r)
					{
						ans[j] = max(ans[j], R[j] - L[j]);
					}
				}
			}
		}
		for (int i = 0; i < m; i++) printf("%d\n", ans[i]);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值