bzoj 2093 [Poi2010]Frog——滑动窗口
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2093
找第k近的可以用一个含k个元素的滑动窗口来实现。
卡空间也还行,但卡时间。不要预处理倍增数组再计算,开一维,一边处理倍增数组一边算答案。不要每次算M次,for(;m;m>>=1)更快。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=1e6+1,M=60; int n,K,hd,tl,to[N],tt[N],ans[N]; ll m,dis[N]; int rdn() { int ret=0;char ch=getchar(); while(ch>'9'||ch<'0')ch=getchar(); while(ch>='0'&&ch<='9')(ret*=10)+=ch-'0',ch=getchar(); return ret; } ll rdl() { ll ret=0;char ch=getchar(); while(ch>'9'||ch<'0')ch=getchar(); while(ch>='0'&&ch<='9')(ret*=10)+=ch-'0',ch=getchar(); return ret; } int main() { n=rdn();K=rdn();m=rdl();K++; //zj是第一近 for(int i=1;i<=n;i++)dis[i]=rdl(); hd=1;tl=K; for(int i=1;i<=n;i++) { ans[i]=i; while(tl<n&&dis[tl+1]-dis[i]<dis[i]-dis[hd])hd++,tl++; to[i]=(dis[tl]-dis[i]>dis[i]-dis[hd]?tl:hd); } if(m&1) for(int i=1;i<=n;i++)ans[i]=to[ans[i]]; m>>=1; for(;m;m>>=1) { for(int j=1;j<=n;j++) tt[j]=to[to[j]]; if(m&1) for(int j=1;j<=n;j++) ans[j]=tt[ans[j]]; for(int j=1;j<=n;j++) to[j]=tt[j]; } for(int i=1;i<=n;i++)printf("%d ",ans[i]); return 0; }