bzoj2093 Frog
2024-09-06 09:57:48
思路
非常有趣的一道题。
先考虑如何找出第K远的位置。
因为给出的序列是单调的,所以对于位置\(i\)的前\(K\)远位置肯定是一个包含位置\(i\)的长度为\(k+1\)的区间。我们用\(l\)表示这个区间的左端点,\(r\)表示这个区间的右端点。那么当\(i+1\)时,\(l\)和\(r\)都只会往右挪。而且往右挪的条件是第\(r+1\)个点与\(i+1\)的距离比第\(l\)个点与第\(i+1\)个点的距离小。
这样就可以找出每个位置的第k远位置。然后就得到了一个置换。
跳\(m\)次也就相当于把这个置换循环\(m\)次。依据倍增的思想只要\(nlogm\)的复杂度就可以完成了。
代码
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N = 1000000 + 100;
ll read() {
ll x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c <= '9' && c >= '0') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
ll a[N];
int b[N],n,k;
ll m;
int tmp[N],c[N];
void calc() {
for(int i = 1;i <= n;++i) c[i] = tmp[i];
for(int i = 1;i <= n;++i) tmp[i] = c[tmp[i]];
}
int main() {
n = read(),k = read(),m = read();\
for(int i = 1;i <= n;++i) a[i] = read();
int l = 1,r = min(k + 1,n);
for(int i = 1;i <= n;++i) {
while((l < i && r < n && a[r + 1] - a[i] < a[i] - a[l]) || r < i) {
++l;++r;
}
if(a[i] - a[l] >= a[r] - a[i]) tmp[i] = l;
else tmp[i] = r;
b[i] = i;
}
for(;m;m >>= 1,calc()) {
if(m & 1) for(int i = 1;i <= n;++i) b[i] = tmp[b[i]];
}
for(int i = 1;i <= n;++i)
printf("%d ",b[i]);
return 0;
}
最新文章
- SQL键值约束、索引使用
- C#线程并发执行的实例[转]
- 【Aizu 2305】Beautiful Currency
- MySQL数据库安装,配置My.ini文件
- C语言:文件操作
- 计算机网络及TCP/IP知识点(全面,慢慢看)
- MySQL删除重复记录只保留一条
- 面试常备题---二叉树总结篇(zt)
- uploadify 下载组件使用技巧和在线预览 word,excel,ppt,pdf的方案
- UVa 1292 - Strategic game (树形dp)
- Android OpenGL 入门示例----绘制三角形和正方形
- 在java中怎样实现多线程?线程的4种状态
- LeetCode第十五题-找出数组中三数和为0的答案
- spring boot 集成axis1.4 java.lang.NoClassDefFoundError: Could not initialize class org.apache.axis.client.AxisClient
- [模板] dp套dp &;&; bzoj5336: [TJOI2018]party
- Android ANR(应用无响应)解决分析【转】
- DAY3(PYTHON)
- ORACLE12C架构图
- CodeForces - 778C: Peterson Polyglot (启发式合并trie树)
- 【jmeter】jmeter环境搭建