[BZOJ3378] [Usaco2004 Open]MooFest 狂欢节(树状数组)
开2个树状数组
一个存的是下标,一个存的是数量
细节。。。看标称吧,懒得说了,好气啊
#include <cstdio> #include <iostream> #include <algorithm> #define N 20001 #define LL long long #define max(x, y) ((x) > (y) ? (x) : (y)) int n, m; LL ans, sum, c[N], d[N]; struct node { LL x, v; }p[N]; inline int read() { int x = 0, f = 1; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; return x * f; } inline bool cmp(node x, node y) { return x.v < y.v; } inline LL query1(int x) { LL ret = 0; for(; x; x -= x & -x) ret += d[x]; return ret; } inline LL query2(int x) { LL ret = 0; for(; x; x -= x & -x) ret += c[x]; return ret; } inline void add1(int x, LL y) { for(; x <= m; x += x & -x) d[x] += y; } inline void add2(int x, LL y) { for(; x <= m; x += x & -x) c[x] += y; } int main() { int i; n = read(); for(i = 1; i <= n; i++) { p[i].v = read(); p[i].x = read(); m = max(m, p[i].x); } std::sort(p + 1, p + n + 1, cmp); for(i = 1; i <= n; i++) { ans += (p[i].x * query2(p[i].x) - query1(p[i].x)) * p[i].v; ans += (sum - query1(p[i].x) - p[i].x * (i - query2(p[i].x) - 1)) * p[i].v; sum += p[i].x; add1(p[i].x, p[i].x); add2(p[i].x, 1); } printf("%lld\n", ans); return 0; }