【题解】Luogu P3509 [POI 2010] ZAB-Frog 倍增dp
单调队列处理第k远的点
倍增跳点
滚(动数组)一维空间就能开下了
注意$m≤10^{18}$的读入
code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace gengyf{ 4 #define ll long long 5 const int maxn=1e6+10; 6 inline ll read(){ 7 ll x=0,f=1; 8 char c=getchar(); 9 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 10 while(c>='0'&&c<='9'){x=(x*10)+c-'0';c=getchar();} 11 return x*f; 12 } 13 ll n,k,m,a[maxn],p[maxn]; 14 int f[maxn][2],g[maxn]; 15 int main(){ 16 n=read();k=read();m=read(); 17 for(int i=1;i<=n;i++){ 18 a[i]=read(); 19 } 20 ll l=1,r=k+1,lim=log2(m)+1; 21 for(int i=1;i<=n;i++){ 22 while(r<n && a[r+1]-a[i]<a[i]-a[l]){ 23 l++,r++; 24 } 25 f[i][0]=(a[r]-a[i]>a[i]-a[l]?r:l); 26 } 27 if(m&1){ 28 for(int i=1;i<=n;i++){ 29 g[i]=f[i][0]; 30 } 31 } 32 else { 33 for(int i=1;i<=n;i++){ 34 g[i]=i; 35 } 36 } 37 r=1;p[0]=1; 38 for(int i=1;i<=lim;i++) p[i]=p[i-1]<<1; 39 for(int j=1;j<=lim;j++){ 40 for(int i=1;i<=n;i++){ 41 f[i][r]=f[f[i][r^1]][r^1]; 42 } 43 if(m&p[j]){ 44 for(int i=1;i<=n;i++){ 45 g[i]=f[g[i]][r]; 46 } 47 } 48 r^=1; 49 } 50 for(int i=1;i<=n;i++){ 51 printf("%d ",g[i]); 52 } 53 return 0; 54 } 55 } 56 signed main(){ 57 gengyf::main(); 58 return 0; 59 }