牛客国庆day3
Leftbest
https://ac.nowcoder.com/acm/contest/7830/A
给定一个序列,如果在之前有,那么找到最小的,把所有这样的相加。
4 2 1 4 3
例如样例就是1前面的2,加上3前面的4。答案为6。
比赛的时候只想到了权值线段树解法,离散化之后维护区间最小值:
struct node { int l, r, k, minn; } tr[400040]; inline void update(int k) { tr[k].minn = min(tr[k * 2].minn, tr[k * 2 + 1].minn); } void build(int k, int l, int r) { tr[k].l = l; tr[k].r = r; if (l == r) { tr[k].minn = INF; return; } int mid = l + r >> 1; build(k * 2, l, mid); build(k * 2 + 1, mid + 1, r); update(k); } void insert(int k, int w) { if (tr[k].l == tr[k].r && tr[k].l == w) { tr[k].minn = w; return; } int mid = tr[k].l + tr[k].r >> 1; if (w <= mid) insert(k * 2, w); else insert(k * 2 + 1, w); update(k); } int query(int k, int l, int r) { if (tr[k].l == l && tr[k].r == r) return tr[k].minn; int mid = tr[k].l + tr[k].r >> 1; if (r <= mid) return query(k * 2, l, r); else if (l > mid) return query(k * 2 + 1, l, r); else return min(query(k * 2, l, mid), query(k * 2 + 1, mid + 1, r)); } int b[100010]; int c[100010]; int a2[100010]; int b2[100010]; struct node2 { int a, c; bool operator<(node2 temp) const { return c < temp.c; } } p[100010]; int main() { int n; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &p[i].a), b[i] = p[i].a; sort(b + 1, b + 1 + n); int len = unique(b + 1, b + 1 + n) - b; for (int i = 1; i <= n; i++) c[i] = p[i].c = lower_bound(b + 1, b + 1 + n, p[i].a) - b; sort(p + 1, p + 1 + n); for (int i = 1; i <= n; i++) { a2[i] = p[i].a; b2[i] = p[i].c; } build(1, 1, 100005); long long ans = 0; for (int i = 1; i <= n; i++) { insert(1, c[i]); int temp = query(1, c[i] + 1, 100005); if (temp == INF) continue; int pos = lower_bound(b2 + 1, b2 + 1 + n, temp) - b2; ans += a2[pos]; } printf("%lld\n", ans); return 0; }
码量挺大的,看到他们的过题速度就知道事情不简单,其实直接用set存前面所有数,二分查找即可:
set<int> st; int main() { int n; long long ans = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) { int temp; scanf("%d", &temp); if (st.upper_bound(temp) != st.end()) ans += *st.upper_bound(temp); st.insert(temp); } printf("%lld\n", ans); return 0; }
有种花,每种花有种,种不同的话可以组成一束花,问最多可以组成多少种花。
赛时用一个小顶堆一个大顶堆维护第k大,wa+tle七发之后瞎猜了一个结论改改过了。赛后发现别人都是二分,(明天一定补。
priority_queue<int, vector<int>, greater<int>> q1; priority_queue<int> q2; int main() { int t; scanf("%d", &t); while (t--) { while (q1.size()) q1.pop(); while (q2.size()) q2.pop(); int n, m; read(n); read(m); for (int i = 1; i <= n; i++) { int temp; read(temp); q1.push(temp); } if (m > n) { printf("0\n"); continue; } while (q1.size() > m) { int temp = q1.top(); q1.pop(); q2.push(temp); } long long ans = 0; while (q1.top() > 1) { int k = q1.top() - 1; ans += k; while (q1.size()) { int temp = q1.top(); q1.pop(); temp -= k; q2.push(temp); } while (q1.size() < m) { int temp = q2.top(); q2.pop(); q1.push(temp); } } while (q1.top()) { int k = q1.top(); ans += k; while (q1.size()) { int temp = q1.top(); q1.pop(); temp -= k; q2.push(temp); } while (q1.size() < m) { int temp = q2.top(); q2.pop(); q1.push(temp); } } printf("%lld\n", ans); } return 0; }