[51Nod 1394 差和问题]树状数组
分类:Data Structure
FenwickedTree
1. 题目链接
2. 题意描述
3. 解题思路
首先离线所有操作,并且所有数字进行离散化。
然后用树状数组维护每个数字出现的次数以及区间和。
对于操作1和操作2,我们可以看成一个单点更新的操作。
但是对于操作3的询问操作,似乎不能直接查询。不过既然答案是全局的,那就可以在操作1和操作2更新之后,记录每次修改对答案的贡献。
4. 实现代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int inf = 0x3f3f3f3f;
const ll infl = 0x3f3f3f3f3f3f3f3fLL;
template<typename T> inline void umax(T &a, T b) { a = max(a, b); }
template<typename T> inline void umin(T &a, T b) { a = min(a, b); }
void debug() { cout << endl; }
template<typename T, typename ...R> void debug (T f, R ...r) { cout << "[" << f << "]"; debug (r...); }
const int MAXN = 100005;
int n, q, m;
ll a[MAXN];
pll tr[MAXN << 1];
void update(int p, int flag, ll v) {
while (p <= m) {
tr[p].first += flag;
tr[p].second += flag * v;
p += p & (-p);
}
}
pll query(int p) {
pll ret(0, 0);
while (p > 0) {
ret.first += tr[p].first;
ret.second += tr[p].second;
p -= p & (-p);
}
return ret;
}
pll query(int l, int r) {
if (l > r) return make_pair(0, 0);
pll lop = query(l - 1), rop = query(r);
return make_pair(rop.first - lop.first, rop.second - lop.second);
}
int main() {
#ifdef ___LOCAL_WONZY___
freopen("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
cin >> n >> q;
vector<ll> f;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
f.push_back(a[i]);
}
vector<pll> qr(q + 1);
ll op, v;
for (int i = 1; i <= q; ++i) {
cin >> op;
if (op == 3) {
qr[i] = pii(3, 0);
} else {
cin >> v;
qr[i] = pii(op, v);
f.push_back(v);
}
}
sort(f.begin(), f.end());
f.erase(unique(f.begin(), f.end()), f.end());
m = f.size();
ll ans = 0;
for (int i = 1; i <= n; ++i) {
int id = lower_bound(f.begin(), f.end(), a[i]) - f.begin() + 1;
update(id, 1, a[i]);
pll lop = query(1, id - 1), rop = query(id + 1, m);
ans += (lop.first * a[i] - lop.second) + (rop.second - rop.first * a[i]);
}
for (int i = 1; i <= q; ++i) {
tie(op, v) = qr[i];
if (op == 3) {
printf("%lld\n", ans);
} else {
int type = op == 1 ? 1 : -1;
int id = lower_bound(f.begin(), f.end(), v) - f.begin() + 1;
if (type == -1 && query(id, id) == pll(0, 0)) {
printf("-1\n");
continue;
}
update(id, type, v);
pll lop = query(1, id - 1), rop = query(id + 1, m);
ans += type * ((lop.first * v - lop.second) + (rop.second - rop.first * v));
}
}
#ifdef ___LOCAL_WONZY___
cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << "ms." << endl;
#endif // ___LOCAL_WONZY___
return 0;
}