【51Nod 1463】找朋友

来源:互联网 发布:淘宝儿童图书商城 编辑:程序博客网 时间:2024/05/17 09:36

Description

给定:
两个长度为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]互不相等

Solution

这是一道需要认真看题的题目。
因为要询问[l,r],所以我们可以考虑一下离线然后限制一个范围。
我们把l倒着排序,不断地减小,限制左边界。
然后,每次增加一个值,那么对其有影响的只有±k,而且看看题目,保证每个b不相等而且都不大于n,那么直接±k然后更新一个f[i]表示l到i的最大值,就好了。
因为还要求一个区间最大值,而且不用加减,所以用树状数组就可以了。

Code

#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;const int maxn=1e5+7;int i,j,l,n,m,ans[maxn],k[11],q,p;int a[maxn],b[maxn],c[maxn];int t[maxn],f[maxn];struct node{    int l,r,c;}wen[maxn];bool cmp(node x,node y){return x.l>y.l;}int lowbit(int x){return x&(-x);}void add(int x,int z){    if(x<0||x>n||c[x]<i)return;    int p=a[c[x]];x=c[x];    for(;x<=n;x+=lowbit(x))t[x]=max(t[x],p+z);}int find(int x){    int z=0;    for(;x;x-=lowbit(x))z=max(z,t[x]);    return z;}int main(){//  freopen("data.in","r",stdin);  //  freopen("fan.in","r",stdin);//  freopen("fan.out","w",stdout);    scanf("%d%d%d",&n,&q,&m);    fo(i,1,n)scanf("%d",&a[i]);    fo(i,1,n)scanf("%d",&b[i]),c[b[i]]=i;    fo(i,1,m)scanf("%d",&k[i]);    fo(i,1,q)scanf("%d%d",&wen[i].l,&wen[i].r),wen[i].c=i;    sort(wen+1,wen+1+q,cmp);    l=n+1;    fo(j,1,q){        fod(i,l-1,wen[j].l){            fo(p,1,m){                add(b[i]-k[p],a[i]);                  add(b[i]+k[p],a[i]);                  l=l;            }            }            l=wen[j].l;        ans[wen[j].c]=find(wen[j].r);    }    fo(i,1,q)printf("%d\n",ans[i]);}
0 0
原创粉丝点击