AtCoder Beginner Contest 287 G Balance Update Query
线段树上二分入门题。
考虑一个贪心:每次询问按 从大到小选。正确性显然。
考虑动态开点值域线段树,每个结点 存 和 。线段树上二分找到第一个 的 ,那么 的 全选, 选的数量根据还能选多少数而定。
时间复杂度 。
code
// Problem: G - Balance Update Query // Contest: AtCoder - UNIQUE VISION Programming Contest 2023 New Year (AtCoder Beginner Contest 287) // URL: https://atcoder.jp/contests/abc287/tasks/abc287_g // Memory Limit: 1024 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) #include <bits/stdc++.h> #define pb emplace_back #define fst first #define scd second #define mems(a, x) memset((a), (x), sizeof(a)) using namespace std; typedef long long ll; typedef unsigned long long ull; typedef double db; typedef long double ldb; typedef pair<ll, ll> pii; const int maxn = 200100; const int N = 1000000000; int n, m, a[maxn], b[maxn]; ll sum[maxn << 7]; int rt, ntot, ls[maxn << 7], rs[maxn << 7], cnt[maxn << 7]; void update(int &rt, int l, int r, int x, ll y) { if (!rt) { rt = ++ntot; } cnt[rt] += y; sum[rt] += x * y; if (l == r) { return; } int mid = (l + r) >> 1; if (x <= mid) { update(ls[rt], l, mid, x, y); } else { update(rs[rt], mid + 1, r, x, y); } } int querycnt(int rt, int l, int r, int ql, int qr) { if (ql > qr || !rt) { return 0; } if (ql <= l && r <= qr) { return cnt[rt]; } int mid = (l + r) >> 1, res = 0; if (ql <= mid) { res += querycnt(ls[rt], l, mid, ql, qr); } if (qr > mid) { res += querycnt(rs[rt], mid + 1, r, ql, qr); } return res; } ll querysum(int rt, int l, int r, int ql, int qr) { if (ql > qr || !rt) { return 0; } if (ql <= l && r <= qr) { return sum[rt]; } int mid = (l + r) >> 1; ll res = 0; if (ql <= mid) { res += querysum(ls[rt], l, mid, ql, qr); } if (qr > mid) { res += querysum(rs[rt], mid + 1, r, ql, qr); } return res; } int find(int rt, int l, int r, int x) { if (l == r) { return l; } int mid = (l + r) >> 1; if (cnt[rs[rt]] > x) { return find(rs[rt], mid + 1, r, x); } else { return find(ls[rt], l, mid, x - cnt[rs[rt]]); } } void solve() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d%d", &a[i], &b[i]); update(rt, 0, N, a[i], b[i]); } scanf("%d", &m); while (m--) { int op, x, y; scanf("%d%d", &op, &x); if (op == 1) { scanf("%d", &y); update(rt, 0, N, a[x], -b[x]); a[x] = y; update(rt, 0, N, a[x], b[x]); } else if (op == 2) { scanf("%d", &y); update(rt, 0, N, a[x], y - b[x]); b[x] = y; } else { int t = querycnt(rt, 0, N, 0, N); if (t < x) { puts("-1"); continue; } if (t == x) { printf("%lld\n", querysum(rt, 0, N, 0, N)); continue; } int pos = find(rt, 0, N, x); ll p = querycnt(rt, 0, N, pos + 1, N), q = querysum(rt, 0, N, pos + 1, N); printf("%lld\n", q + (x - p) * pos); } } } int main() { int T = 1; // scanf("%d", &T); while (T--) { solve(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端