洛谷P3586 [POI2015]LOG(贪心 权值线段树)
程序员文章站
2022-05-18 23:24:23
题意 "题目链接" Sol 显然整个序列的形态对询问没什么影响 设权值$ =s$的有$k$个。 我们可以让这些数每次都被选择 那么剩下的数,假设值为$a_i$次,则可以$a_i$次被选择 一个显然的思路是每次选最大的C个 那么只需要判断$\sum a_i =(c k) s$即可 权值线段树维护一下 ......
题意
sol
显然整个序列的形态对询问没什么影响
设权值\(>=s\)的有\(k\)个。
我们可以让这些数每次都被选择
那么剩下的数,假设值为\(a_i\)次,则可以\(a_i\)次被选择
一个显然的思路是每次选最大的c个
那么只需要判断\(\sum a_i >=(c - k)*s\)即可
权值线段树维护一下
#include<bits/stdc++.h> #define pair pair<int, int> #define mp(x, y) make_pair(x, y) #define fi first #define se second #define ll long long #define fin(x) {freopen(#x".in","r",stdin);} #define fout(x) {freopen(#x".out","w",stdout);} using namespace std; const int maxn = 1e6 + 10, mod = 1e9 + 7, inf = 1e9 + 10; const double eps = 1e-9; template <typename a, typename b> inline bool chmin(a &a, b b){if(a > b) {a = b; return 1;} return 0;} template <typename a, typename b> inline bool chmax(a &a, b b){if(a < b) {a = b; return 1;} return 0;} template <typename a, typename b> inline ll add(a x, b y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;} template <typename a, typename b> inline void add2(a &x, b y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);} template <typename a, typename b> inline ll mul(a x, b y) {return 1ll * x * y % mod;} template <typename a, typename b> inline void mul2(a &x, b y) {x = (1ll * x * y % mod + mod) % mod;} template <typename a> inline void debug(a a){cout << a << '\n';} template <typename a> inline ll sqr(a x){return 1ll * x * x;} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int a[maxn], n, m; const int ss = maxn * 10 + 10, mx = 1e9 + 10; int ls[ss], rs[ss], num[ss], tot, root; ll sum[ss]; void update(int k) { sum[k] = sum[ls[k]] + sum[rs[k]]; num[k] = num[ls[k]] + num[rs[k]]; } void modify(int &k, int l, int r, int p, int v) { if(!k) k = ++tot; if(l == r) { num[k] += (v < 0 ? -1 : 1); sum[k] += v; return ; } int mid = l + r >> 1; if(p <= mid) modify(ls[k], l, mid, p, v); else modify(rs[k], mid + 1, r, p, v); update(k); } int querynum(int k, int l, int r, int ql, int qr) { if(!k) return 0; if(ql <= l && r <= qr) return num[k]; int mid = l + r >> 1; if(ql > mid) return querynum(rs[k], mid + 1, r, ql, qr); else if(qr <= mid) return querynum(ls[k], l, mid, ql, qr); else return querynum(ls[k], l, mid, ql, qr) + querynum(rs[k], mid + 1, r, ql, qr); } ll querysum(int k, int l, int r, int ql, int qr) { if(!k) return 0; if(ql <= l && r <= qr) return sum[k]; int mid = l + r >> 1; if(ql > mid) return querysum(rs[k], mid + 1, r, ql, qr); else if(qr <= mid) return querysum(ls[k], l, mid, ql, qr); else return querysum(ls[k], l, mid, ql, qr) + querysum(rs[k], mid + 1, r, ql, qr); } signed main() { n = read(); m = read(); while(m--) { char s[3]; scanf("%s", s); int x = read(), y = read(); if(s[0] == 'u') {//a[x] = y if(a[x]) modify(root, 1, mx, a[x], -a[x]); a[x] = y; if(y) modify(root, 1, mx, y, y); } else {//choose x = c turn y = s int k = querynum(1, 1, mx, y, mx); ll sum = querysum(1, 1, mx, 1, y - 1); puts((sum >= 1ll * (x - k) * y) ? "tak" : "nie"); } } return 0; } /* 7 -1 160 -2000 14 82 61 85 41 10 34 */
上一篇: java网络编程以及通信的项目研究
下一篇: Java实现中序表达式