开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;
}