Codeforces Beta Round #12 (Div 2 Only) D. Ball 树状数组查询后缀最值
Posted stupid_one
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Beta Round #12 (Div 2 Only) D. Ball 树状数组查询后缀最值相关的知识,希望对你有一定的参考价值。
http://codeforces.com/problemset/problem/12/D
这里的BIT查询,指的是查询[1, R]或者[R, maxn]之间的最值,这样就够用了。
设三个权值分别是b[1], b[2], b[2];
首先,先把b[1]值离散化,离散成一个个id,那么只能是在id比较大的地方找了。然后把b[2]排序,倒序查询,也就是先查询最大的,当然它是没可能自杀的,因为它已经最大了,然后查询完后,把它压进bit后,以后在bit查询,就不需要管b[2]了,因为在bit里面的b[2]永远都是较大者,其实这是一个常用的方法啦。hack点是相同的值不能提前更新,细节看代码 + 慢慢debug
现在说说bit的作用,bit维护的是b[3],因为我们已经离散化b[1]了,那么每一个元素的下标就相当于离散化的b[1],所以加进去BIT的时候用id做下标即可。bit维护后缀最大值。
hack点的意思是,假如你的a[i].b[2] == a[j].b[2],那么不能在查询a[j]前提前把a[i]加入bit,因为bit查询默认是b[2]成立的,但是提前更新了的话,不成立。
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define ios ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> #include <bitset> #include <stack> const int maxn = 5e5 + 20; int c[maxn], en; int lowbit(int x) { return x & (-x); } void upDate(int pos, int val) { while (pos) { c[pos] = max(c[pos], val); pos -= lowbit(pos); } } int ask(int pos) { int ans = -1; while (pos <= en) { ans = max(ans, c[pos]); pos += lowbit(pos); } return ans; } struct Node { int a[5], id; }a[maxn]; stack<int> st; bool cmp0(struct Node a, struct Node b) { return a.a[1] < b.a[1]; } bool cmp1(struct Node a, struct Node b) { return a.a[2] < b.a[2]; } void work() { int n; scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i].a[1]); for (int i = 1; i <= n; ++i) scanf("%d", &a[i].a[2]); for (int i = 1; i <= n; ++i) scanf("%d", &a[i].a[3]); sort(a + 1, a + 1 + n, cmp0); en = 1; a[1].id = en; for (int i = 2; i <= n; ++i) { if (a[i].a[1] == a[i - 1].a[1]) { a[i].id = en; } else a[i].id = ++en; } en += 2; memset(c, -1, sizeof c); sort(a + 1, a + 1 + n, cmp1); // for (int i = 1; i <= n; ++i) { // cout << a[i].a[1] << " " << a[i].a[2] << " " << a[i].a[3] << " " << a[i].id << endl; // } st.push(n); int ans = 0; for (int i = n - 1; i >= 1; --i) { if (a[i].a[2] == a[i + 1].a[2]) { st.push(i); int res = ask(a[i].id + 1); ans += res > a[i].a[3]; } else { while (!st.empty()) { int res = st.top(); st.pop(); upDate(a[res].id, a[res].a[3]); } int res = ask(a[i].id + 1); ans += res > a[i].a[3]; st.push(i); // upDate(a[i].id, a[i].a[3]); } } cout << ans << endl; } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif work(); return 0; }
以上是关于Codeforces Beta Round #12 (Div 2 Only) D. Ball 树状数组查询后缀最值的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Beta Round #12 (Div 2 Only) D. Ball 树状数组查询后缀最值