给定:
两个长度为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
思路:把询问区间按右端点排序,因为1<=B[i]<=n,所以可以通过K数组找到另一个B[j]值,同时用数组maxsum记录在 j 之前的最大值,如果存在有合法的B[i],B[j]的情况下,A[i]+A[j]大于maxsum[j],则更新树状数组,每更新完一个询问区间,更新一遍答案(如果把所有询问区间处理完后再处理答案,会存在区间覆盖得情况)
#include <bits/stdc++.h>
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const double eps=1e-8;
const double Pi=acos(-1.0);
const int N= 100005;
struct Quetion
{
int l,r,c;
} Q[N];
int n,q,m;
int a[N],b[N],h[N],c[N],mark[N],k[15],maxsum[N],ans[N];
int lowbit(int x)
{
return x&(-x);
}
void update(int x)
{
int lx;
while(x<=n)
{
h[x]=c[x];
lx=lowbit(x);
for(int i=1; i<lx; i<<=1)
h[x]=max(h[x],h[x-i]);
x+=lowbit(x);
}
}
int query(int x,int y)
{
int ans=0;
while(x<=y)
{
ans=max(c[y],ans);
y--;
for(; y-lowbit(y)>=x; y-=lowbit(y))
ans=max(h[y],ans);
}
return ans;
}
bool cmp1(Quetion a,Quetion b)
{
return a.r<b.r;
}
int main()
{
//FIN;
memset(c,0,sizeof(c));
memset(h,0,sizeof(h));
for(int i=0;i<N;i++)
mark[i]=INF;
scanf("%d %d %d",&n,&q,&m);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=1; i<=n; i++)
scanf("%d",&b[i]),mark[b[i]]=i;
for(int i=1; i<=m; i++)
scanf("%d",&k[i]);
for(int i=1; i<=q; i++)
scanf("%d %d",&Q[i].l,&Q[i].r),Q[i].c=i;
sort(Q+1,Q+q+1,cmp1);
int num,idx;
Q[0].r=1;
for(int o=1;o<=q;o++)
{
for(int i=Q[o-1].r;i<=Q[o].r;i++)
{
for(int j=1;j<=m;j++)
{
num=b[i]+k[j];
idx=mark[num];
if(num<=n&&idx<i&&(a[i]+a[idx]>maxsum[idx]))
{
maxsum[idx]=a[i]+a[idx];
c[idx]=maxsum[idx];
update(idx);
}
num=b[i]-k[j];
idx=mark[num];
if(num>=1&&idx<i&&(a[i]+a[idx]>maxsum[idx]))
{
maxsum[idx]=a[i]+a[idx];
c[idx]=maxsum[idx];
update(idx);
}
}
}
ans[Q[o].c]=query(Q[o].l,Q[o].r);
}
//puts("-----------------------");
for(int i=1;i<=q;i++)
printf("%d\n",ans[i]);
}