C. Monsters (hard version)
C. Monsters (hard version)
思路
最终肯定是一个阶梯的数组,思考怎么维护阶梯,那些数加进来是无用的。
用线段树来维护每个数出现的次数。
代码
/* 最后形成的一定是一个阶梯状的数组 如果新加进来一个数,判断他是否是有用的,就是是不是有没有他都无所谓。 也就是不需要他去顶替谁的位置,这样子的话他也就是没有用的 直接删除就可以了。 用线段树来进行维护前缀和,每个点的值设置为-i,这样子容易判断是否有无用的 无用的就进行删除 */ #include <bits/stdc++.h> using namespace std; #define ul (u << 1) #define ur (u << 1 | 1) const int M = 2e5 + 5; struct Tree { int l, r, mx, la; }tr[M << 2]; void pu(int u) { tr[u].mx = max(tr[ul].mx, tr[ur].mx); } void pd(int u) { if(!tr[u].la)return ; tr[ul].la += tr[u].la; tr[ur].la += tr[u].la; tr[ul].mx += tr[u].la; tr[ur].mx += tr[u].la; tr[u].la = 0; } void build(int u, int l, int r) { tr[u] = {l, r, -l , 0}; if(l == r)return ; int mid = (l + r) / 2; build(ul, l, mid); build(ur, mid + 1, r); pu(u); } void up(int u, int l, int r, int v) { if(tr[u].l >= l && tr[u].r <= r) { tr[u].la += v; tr[u].mx += v; return ; } if(tr[u].l > r || tr[u].r < l)return ; pd(u); up(ul, l, r, v); up(ur, l, r, v); pu(u); } int query(int u) { if(tr[u].l == tr[u].r)return tr[u].l; pd(u); if(tr[ul].mx > 0)return query(ul); return query(ur); } int a[M]; int main() { int TT; cin >> TT; while(TT--) { int n; cin >> n; build(1, 1, n); for(int i = 1; i <= n; i++)cin >> a[i]; long long cnt = 0, sum = 0; for(int i = 1; i <= n; i++) { cnt++; sum += a[i]; up(1, a[i], n, 1); if(tr[1].mx > 0) { int p = query(1); up(1, p, n, -1); cnt--; sum -= p; } cout << (sum - cnt * (cnt + 1) / 2) << ' '; } cout << '\n'; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现