标签:ace turn 控制 return while include abs 关于 mat
蛤的旅行
[题目描述]
长江的江心有n块石头。为了简化问题,我们把长江看做一条数轴,且所有石头的坐标均为正整数。
有一只蛤在这些石头上跳。这只蛤在长江中生活了数百年,多年与风浪搏斗的经验使他锻炼出了极强的跳跃能力,可以瞬间从一块石头跳到与其相距任意远的另一块石头上。
然而,在一次意外进入一片诡异的灌木林(bush)之后,这只蛤发现自己获得了一个自己无法控制的buff:改变天气。具体来说,蛤周围方圆数百里(足以覆盖所有石头)之内都会大雨滂沱,洪水泛滥,甚至连江心的石头都会因此而淹没。只有一块地方形成了一个异常的高压区,天气晴朗,石头也没有被淹没——巧合的是,没有被淹没的石头有且仅有一块,且恰好是距离蛤第m远的那块(如果有两块石头距离蛤一样远,则我们认为坐标较大的那块更远)。因此蛤很尴尬地发现自己只能跳到那块石头上了。
现在蛤想要知道:如果他一开始在第S块石头上,那么在跳了C次之后他会在哪块石头上?他给出了q次询问,要求你在1s内回答。
[输入格式]
第一行,两个正整数n,m,表示石头的数量,没有被淹没的石头距离自己第几远。
第二行,n个正整数X[i],表示石头的坐标。保证坐标单调递增。
第三行,一个正整数q,表示询问数。
接下来q行,每行两个正整数S,C,表示蛤一开始所在的石头以及跳的步数。
[输出格式]
对于每个询问输出一行,表示蛤最终所在的石头编号。
[输入样例]
6 3
1 6 8 10 11 15
6
1 3
2 4
3 4
4 3
5 2
6 3
[输出样例]
1
1
5
4
3
6
[数据范围]
对于40%的数据,2<=n<=1000,1<=q<=1000,1<=X[i]<=1e9,1<=C<=10000。
对于100%的数据,2<=n<=100000,1<=m<=n-1,1<=X[i]<=1e18,1<=q<=100000,1<=S<=n,1<=C<=100000。
题目描述很多坑:比如自己不算;第m远(很容易写成第m近)。
然后就可以类似LCA的二进制拆分了。设st[i][j]表示从i开始跳\(2^j\)次的点的编号。于是只要知道所有的st[i][0]就可以知道所有的st[i][j],做到 \(O(\log n)\)查询。
关于st[i][0],考虑双指针,可以 \(O(n)\) 搞定。开始l=1,r=n-m+1.当dis(i,r+1)<dis(i,l)的时候说明最小的m个数可以更新,则++l,++r.每次st[i][0]取dis(i,l)和dis(i,r)较大的那个(l或r)。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=300000;
int st[N][19],ln=18;
int n,m,x[N],q;
int abss(int a)
{
return a>0?a:-a;
}
int dis(int i,int j) {
return abss(x[j]-x[i]);
}
signed main() {
scanf("%lld%lld",&n,&m);
for(int i=1; i<=n; ++i)scanf("%lld",&x[i]);
int l=1,r=n-m+1;
for(int i=1; i<=n; ++i) {
while(dis(i,r+1)<dis(l,i))++l,++r;
st[i][0]=dis(l,i)>=dis(i,r)?l:r;
}
for(int j=1; j<=ln; ++j)
for(int i=1; i<=n; ++i)
st[i][j]=st[st[i][j-1]][j-1];
scanf("%lld",&q);
int s,c;
while(q--) {
scanf("%lld%lld",&s,&c);
for(int i=0;i<=ln;++i)
if(c&(1<<i))s=st[s][i];
printf("%lld\n",s);
}
return 0;
}
标签:ace turn 控制 return while include abs 关于 mat
原文地址:https://www.cnblogs.com/zzctommy/p/12343193.html