给定:
两个长度为n的数列A 、B
一个有m个元素的集合K
询问Q次
每次询问[l,r],输出区间内满足|Bi-Bj|∈K 的最大Ai+Aj
数据约定:
n,Q<=100000
m <= 10
0<=A[i]<=1000000000
1<=B[i]<=n
1<=K[i]<=n
保证B[i]互不相等
Input
n Q m
A1 A2 ....An
B1 B2 ....Bn
K1 K2 ....Km
l1 r1
l2 r2
.
.
lQ rQ
Output
Q行,每行一个整数表示相对应的答案。
如果找不到这样的两个数则输出0。
Input示例
4 2 2
1 2 3 4
3 2 1 4
1 3
1 4
2 3
Output示例
7
5
思路:
将区间按照左端点从大到小排序,依次扫描。在扫描每个点x时,依次遍历k的元素y,如果 a[x+y]或a[x-y]存在,则更新a的最大值。更新时利用扫描线原理,获取最大值时同理。
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 1e5 + 5;
struct Range
{
int left, right, index;
};
Range ranges[MAXN];
int f[MAXN], a[MAXN], b[MAXN], c[MAXN], d[MAXN], result[MAXN];
int n, q, m, z;
bool cmp(Range x, Range y)
{
return x.left > y.left;
}
int lowbit(int x)
{
return x & (-x);
}
void insert(int x)
{
if (x > n)
{
return;
}
f[x] = max(f[x], z);
insert(x + lowbit(x));
}
void make(int j, int x)
{
if (x < 0 || !d[x] || x > n)
{
return;
}
z = a[j] + a[d[x]];
insert(d[x]);
}
int find(int x)
{
if (x < 1)
{
return 0;
}
return max(f[x], find(x - lowbit(x)));
}
int main()
{
cin >> n >> q >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i <= n; i++)
{
cin >> b[i];
}
for (int i = 1; i <= m; i++)
{
cin >> c[i];
}
for (int i = 1; i <= q; i++)
{
cin >> ranges[i].left >> ranges[i].right;
ranges[i].index = i;
}
sort(ranges + 1, ranges + q + 1, cmp);
ranges[0].left = n + 1;
for (int i = 1; i <= q; i++)
{
for (int j = ranges[i-1].left - 1; j >= ranges[i].left; j--)
{
for (int k = 1; k <= m; k++)
{
make(j, b[j] + c[k]);
make(j, b[j] - c[k]);
}
d[b[j]] = j;
}
result[ranges[i].index] = find(ranges[i].right);
}
for (int i = 1;i <= q; i++)
{
cout << result[i] << endl;
}
return 0;
}