BZOJ2093: [Poi2010]Frog
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2093
题解:Orz这题好神!
首先求一位数轴上距离每个点第k近的点。
神做法:维护一个l,r表示a[l--r]是距离i最近的k个点,当i++时,只有可能l++,r++或不改变!!!
然后比较两端距离大小就是第k大!!主要运用了待查询点往右移动时距离他最近的k个元素组成一个区间并且左右端点都单调不减!!!
然后是倍增m,我以为处理处f[i][j]表示i走2^j步之后在哪里,每个倍增一次就好了。没想到卡空间!!!
于是又orz了claris:
while(m) { if(m&1) { for1(i,n)t[i]=f[g[i]]; for1(i,n)g[i]=t[i]; } m>>=1; for1(i,n)t[i]=f[f[i]]; for1(i,n)f[i]=t[i]; }
跪烂!!!!
代码:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #include<string> 12 #define inf 1000000000 13 #define maxn 1000000+5 14 #define maxm 100000+5 15 #define eps 1e-10 16 #define ll long long 17 #define pa pair<int,int> 18 #define for0(i,n) for(int i=0;i<=(n);i++) 19 #define for1(i,n) for(int i=1;i<=(n);i++) 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 22 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 23 #define mod 1000000007 24 using namespace std; 25 inline ll read() 26 { 27 ll x=0,f=1;char ch=getchar(); 28 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 29 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 30 return x*f; 31 } 32 int n,k,f[maxn],g[maxn],t[maxn]; 33 ll m,a[maxn]; 34 int main() 35 { 36 freopen("input.txt","r",stdin); 37 freopen("output.txt","w",stdout); 38 n=read();k=read();m=read(); 39 for1(i,n)a[i]=read(); 40 int l=1,r=k+1;f[1]=k+1; 41 for2(i,2,n) 42 { 43 while(r<n&&a[r+1]-a[i]<a[i]-a[l])l++,r++; 44 f[i]=a[r]-a[i]>a[i]-a[l]?r:l; 45 } 46 for1(i,n)g[i]=i; 47 while(m) 48 { 49 if(m&1) 50 { 51 for1(i,n)t[i]=f[g[i]]; 52 for1(i,n)g[i]=t[i]; 53 } 54 m>>=1; 55 for1(i,n)t[i]=f[f[i]]; 56 for1(i,n)f[i]=t[i]; 57 } 58 for1(i,n)printf("%d%c",g[i],i==n?'\n':' '); 59 return 0; 60 }