【题解】Luogu P3509 [POI 2010] ZAB-Frog 倍增dp

单调队列处理第k远的点

倍增跳点

滚(动数组)一维空间就能开下了

注意$m≤10^{18}$的读入

code

 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 }
View Code

 

posted @ 2019-10-05 19:24  喵の耳  阅读(171)  评论(0编辑  收藏  举报