1 条题解
-
0
大意
一共 个点,将这 个点进行 次操作,每次同时将 个点移动到离这个点距离第 小的点,问最后这 个点的坐标。
思路
根据题目,我们可以想出,用单调队列 + 快速幂就可以解决此问题。我们用 表示距离第 个点的第 小的点,用 去存答案,每次移动用快速幂更新即可。
单调队列显然用于初始化 , 也就需要让 和 相差 。
其他就没什么了,具体请参见代码。
#include <bits/stdc++.h using namespace std; typedef long long ll; //!!! ll n, m; ll k; ll a[1000001]; int nxt[1000001]; //nxt[i]表示距离第i个点的第k小的点的编号 int tmp[1000001]; int ans[1000001]; //存答案 int main() { speed: std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); //加速 cin >> n >> k >> m; for(int i = 1; i <= n; i++) //读入坐标 cin >> a[i]; nxt[1] = k + 1; //注意!是k + 1而不是1!!! int head = 1, tail = k + 1; //队首,队尾,距离保持k for(int i = 2; i <= n; i++) //进行初始(单调队列) { while(tail + 1 <= n && a[i] - a[head] > a[tail + 1] - a[i]) head++, tail++; //下面开始记录 if(a[i] - a[head] >= a[tail] - a[i]) nxt[i] = head; else nxt[i] = tail; } for(int i = 1; i <= n; i++) ans[i] = i; //移动0次就是原先的样子 while(m) //快速幂 { if(m & 1) //相当于m % 2 == 1 for(int i = 1; i <= n; i++) //肯定要更新啊! ans[i] = nxt[ans[i]]; memcpy(tmp, nxt, sizeof(tmp)); //暂时存一下,方便后面使用 for(int i = 1; i <= n; i++) nxt[i] = tmp[tmp[i]]; //更新下一个移动到的点 m >>= 1; //相当于m /= 2 } for(int i = 1; i <= n; i++) cout << ans[i] << " "; return 0; }
- 1
信息
- ID
- 3758
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者