【题解】 luogu P3203 [HNOI2010] 弹飞绵羊
题目传送门:P3203 [HNOI2010] 弹飞绵羊
题意
- 修改一个数
- 从
开始跳, , 几次能够跳出序列
分析
数据范围比较大,单纯搜索模拟肯定会T,那么考虑每次让他跳一段就停止,然后把每一段跳的次数加起来就是答案;修改也简单,直接在这一段里面使用暴力就行。
题解
可以是LCT板子题,但是还没学LCT,本次采用分块思想:
表示从 跳几次可以跳到下一个块中, 表示从 跳到下一个块的位置, 记录每个块的开头- 修改和查询的时间复杂度均为
AC代码
#include<bits/stdc++.h> #define int long long using namespace std; const int N = 2e5 + 10; int k[N], bk[N], fir[N]; int n, m; int f[N], to[N]; inline void rep(int p, int w) { k[p] = w; for(int i = fir[bk[p] + 1] - 1; i >= fir[bk[p]]; --i) { if(i + k[i] >= fir[bk[i] + 1]) { f[i] = 1; to[i] = i + k[i]; } else { f[i] = f[i + k[i]] + 1; to[i] = to[i + k[i]]; } } } inline void query(int p) { int ans = 0; while(p <= n) { ans += f[p]; p = to[p]; } std::cout << ans << endl; } inline void solve() { std::cin >> n; int bl = sqrt(n); for(int i = 1; i <= n; ++i) { std::cin >> k[i]; bk[i] = i % bl == 0 ? i / bl : i / bl + 1; if(bk[i] != bk[i - 1]) fir[bk[i]] = i; } fir[n + 1] = n + 1; for(int i = n; i >= 1; --i) { if(i + k[i] >= fir[bk[i] + 1]) { f[i] = 1; to[i] = i + k[i]; } else { f[i] = f[i + k[i]] + 1; to[i] = to[i + k[i]]; } } std::cin >> m; while(m --) { int t, p, w; std::cin >> t; if(t == 1) { cin >> p; query(p + 1); } else { cin >> p >> w; rep(p + 1, w); } } return; } signed main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int T; T = 1; while(T --) { solve(); } return 0; }
本文作者:shikean@Tianjin University
本文链接:https://www.cnblogs.com/keanshi/p/17579204.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步