http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463

题意:

思路:

好题!

先对所有查询进行离线处理,按照右区间排序,因为k一共最多只有10个,所有在该区间内的B数组,每次枚举K值,通过这样的方式来得到另外一个B值。但是这样得到的B值它在B数组中的位置必须在当前数的左边。如下图:(j为当前数在B数组中的位置,pos为计算得到的另一个B值在数组中的位置)

这两个数的和记录在pos中,这里pos的位置必须在j的左边,假设第q个查询区间如上图所示(请在脑中将pos和j互换一下),那么此时j就没包含在该区间内,这样一来,查询得到的值就会有错。因为我们是按照右区间排序的,所以右区间会不断扩大,只要左边被覆盖的,那么右边的数肯定是在该区间内的。

用线段树维护即可。具体请参见代码。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=1e5+; int n,q,m;
int A[maxn],B[maxn],K[],B_pos[maxn],ans[maxn]; struct node
{
int l,r,id;
bool operator<(const node& rhs) const
{
return r<rhs.r;
}
}Q[maxn]; int MAX[maxn<<];
int val[maxn<<]; void build(int l, int r, int o)
{
val[o]=;
if(l==r) return;
int mid=(l+r)>>;
build(l,mid,o<<);
build(mid+,r,o<<|);
} void update(int l, int r, int pos, int x, int o)
{
val[o]=max(val[o],x);
if(l==pos && r==pos) return;
int mid=(l+r)>>;
if(pos<=mid) update(l,mid,pos,x,o<<);
else update(mid+,r,pos,x,o<<|);
} int query(int ql, int qr, int l, int r, int o)
{
if(ql<=l && qr>=r) return val[o];
int mid=(l+r)>>;
int res=;
if(ql<=mid) res=max(res,query(ql,qr,l,mid,o<<));
if(qr>mid) res=max(res,query(ql,qr,mid+,r,o<<|));
return res;
} int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%d%d",&n,&q,&m);
for(int i=;i<=n;i++) scanf("%d",&A[i]);
for(int i=;i<=n;i++) {scanf("%d",&B[i]);B_pos[B[i]]=i;}
for(int i=;i<=m;i++) scanf("%d",&K[i]);
for(int i=;i<=q;i++)
{
scanf("%d%d",&Q[i].l,&Q[i].r);
Q[i].id=i;
}
sort(Q+,Q+q+);
build(,n,);
int s=;
memset(MAX,,sizeof(MAX));
for(int i=;i<=q;i++)
{
int r=Q[i].r;
for(int j=s;j<=r;j++)
{
for(int k=;k<=m;k++)
{
int tmp_B=B[j]+K[k];
int pos=B_pos[tmp_B]; //得到tmp_B在B数组中的位置
if(tmp_B<=n && pos<j && A[pos]+A[j]>MAX[pos])
{
MAX[pos]=A[pos]+A[j]; //此时pos位置的最大值是由pos和[1,j)之间的一个数相加而成
update(,n,pos,MAX[pos],); //更新线段树
}
tmp_B=B[j]-K[k];
pos=B_pos[tmp_B];
if(tmp_B>= && pos<j && A[pos]+A[j]>MAX[pos])
{
MAX[pos]=A[pos]+A[j];
update(,n,pos,MAX[pos],);
}
}
}
ans[Q[i].id]=query(Q[i].l,Q[i].r,,n,); //查询该区间内的最大值
s=r;
}
for(int i=;i<=q;i++) printf("%d\n",ans[i]);
return ;
}

再给一个树状数组的吧,按照左区间从大到小排序。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=1e5+; int n,q,m;
int A[maxn],B[maxn],K[],B_pos[maxn],ans[maxn],c[maxn]; struct node
{
int l,r,id;
bool operator<(const node& rhs) const
{
return l>rhs.l;
}
}Q[maxn]; int lowbit(int x)
{
return x&(-x);
} int find_max(int x)
{
int res=;
while(x>)
{
res=max(res,c[x]);
x-=lowbit(x);
}
return res;
} void update(int x, int val)
{
while(x<=n)
{
c[x]=max(c[x],val);
x+=lowbit(x);
}
} int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%d%d",&n,&q,&m);
for(int i=;i<=n;i++) scanf("%d",&A[i]);
for(int i=;i<=n;i++) {scanf("%d",&B[i]);B_pos[B[i]]=i;}
for(int i=;i<=m;i++) scanf("%d",&K[i]);
for(int i=;i<=q;i++)
{
scanf("%d%d",&Q[i].l,&Q[i].r);
Q[i].id=i;
}
sort(Q+,Q+q+);
memset(c,,sizeof(c));
int s=n+;
for(int i=;i<=q;i++)
{
for(int j=s-;j>=Q[i].l;j--)
{
for(int k=;k<=m;k++)
{
int tmp_B=B[j]+K[k];
int pos=B_pos[tmp_B];
if(tmp_B<=n && pos>j)
{
update(pos,A[pos]+A[j]);
}
tmp_B=B[j]-K[k];
pos=B_pos[tmp_B];
if(tmp_B>= && pos>j)
{
update(pos,A[pos]+A[j]);
}
}
}
s=Q[i].l;
ans[Q[i].id]=find_max(Q[i].r);
} for(int i=;i<=q;i++) printf("%d\n",ans[i]);
return ;
}

51nod 1463 找朋友(线段树+离线处理)的更多相关文章

  1. 51nod 1463 找朋友 (扫描线+线段树)

    1463 找朋友  基准时间限制:1.5 秒 空间限制:262144 KB 分值: 80 难度:5级算法题  收藏  关注 给定: 两个长度为n的数列A .B 一个有m个元素的集合K 询问Q次 每次询 ...

  2. 线段树+离线 hdu5654 xiaoxin and his watermelon candy

    传送门:点击打开链接 题意:一个三元组假设满足j=i+1,k=j+1,ai<=aj<=ak,那么就好的.如今告诉你序列.然后Q次询问.每次询问一个区间[l,r],问区间里有多少个三元组满足 ...

  3. 牛客练习赛53 E-老瞎眼pk小鲜肉(思维+线段树+离线)

    前言 听说是线段树离线查询?? 做题做着做着慢慢对离线操作有点感觉了,不过也还没参透,等再做些题目再来讨论离线.在线操作. 这题赛后看代码发现有人用的树状数组,$tql$.当然能用树状数组写的线段树也 ...

  4. HDU 4638-Group(线段树+离线处理)

    题意: 给n个编号,m个查询每个查询l,r,求下标区间[l,r]中能分成标号连续的组数(一组内的标号是连续的) 分析: 我们认为初始,每个标号为一个组(线段树维护区间组数),从左向右扫序列,当前标号, ...

  5. HDU 4630-No Pain No Game(线段树+离线处理)

    题意: 给你n个数的序列a,q个询问,每个询问给l,r,求在下标i在[l,r]的区间任意两个数的最大公约数中的最大值 分析: 有了hdu3333经验,我们从左向右扫序列,如果当前数的约数在前面出现过, ...

  6. HDU 4288 Coder 【线段树+离线处理+离散化】

    题意略. 离线处理,离散化.然后就是简单的线段树了.需要根据mod 5的值来维护.具体看代码了. /* 线段树+离散化+离线处理 */ #include <cstdio> #include ...

  7. SPOJ--K-query (线段树离线) 离线操作解决一些问题

    K-query Given a sequence of n numbers a1, a2, ..., an and a number of k- queries. A k-query is a tri ...

  8. lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs 倍增

    https://www.luogu.org/problemnew/show/P3379 1.欧拉序+rmq(st) /* 在这里,对于一个数,选择最左边的 选择任意一个都可以,[left_index, ...

  9. 玲珑oj 1117 线段树+离线+离散化,laz大法

    1117 - RE:从零开始的异世界生活 Time Limit:1s Memory Limit:256MByte Submissions:438Solved:68 DESCRIPTION 486到了异 ...

随机推荐

  1. js-jquery-插件开发(二)【最终插件是最后一个,中间是过程】

    二.通过$.fn 向jQuery添加新的方法 2.1.基本格式: $.fn.pluginName = function() { //your code goes here } 说明:在$.fn后面添加 ...

  2. 1.如何修改oracle的密码

    在下图中的目录下面找到 PWDorcl.ora 文件,orcl是数据库的实例名  备份,将PWDorcl.ora 文件名称改为 PWDorcl_back.ora 以管理员身份打开cmd,执行 orap ...

  3. 设置pip的默认源

    Python在导入第三方模块的时候用设置豆瓣源的方法提高效率,每次设置很麻烦,所以通过下面方法设置默认源,这样就可以直接pip install package,而不用指定源了. [global] ti ...

  4. [LeetCode] 394. Decode String_Medium tag: stack 666

    Given an encoded string, return it's decoded string. The encoding rule is: k[encoded_string], where ...

  5. [LeetCode] 561. Array Partition I_Easy tag: Sort

    Given an array of 2n integers, your task is to group these integers into n pairs of integer, say (a1 ...

  6. 使用sys用户创建其他用户下的dblink

    因为dblink的创建和删除只能是它的所属用户来操作,所以我们无法直接使用sys用户创建其他用户下的dblink,当遇到有这样的需求时,可以先建立该用户下存储过程,再通过调用这个存储过程来间接实现. ...

  7. mysql数据库给别人访问权限

    注:本操作是在WIN命令提示符下,phpMyAdmin同样适用. 用户:phplamp  用户数据库:phplampDB 1.新建用户. //登录MYSQL @>mysql -u root -p ...

  8. 007-配置IP和DNS

    2.配置DNS. 3.

  9. JSP—内置对象

    JSP内置对象是Web容器创建的一组对象,不用声明,直接使用 out 输出对象 类型 javax.servlet.jsp.JspWriter 作用域 Page request 请求对象 类型 java ...

  10. Trove系列(四)—Trove的快照功能介绍

    Trove 快照用于支持DbaaS 备份,复制等功能.在Trove API (guest_agent)上将支持本功能.本功能将能够支持快照,从而用来进行副本设置,主数据库克隆和备份,以及数据恢复.目前 ...