思路和poj1990一样,开两个树状数组,分别维护左右的数量和距离和。
注意要使用long long。
代码:
#include
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
ll tree_num[maxn], tree_dis[maxn];
struct node
{
int x, h, rx, rh;
}a[maxn];
bool cmp(const node &x, const node &y)
{
return x.rh > y.rh;
}
bool cmp1(const node &x, const node y)
{
return x.x < y.x;
}
bool cmp2(const node &x, const node &y)
{
return x.h < y.h;
}
int lowbit(int x) { return x&(-x); }
void update(ll *tree, int pos, int val)
{
while(pos < maxn)
{
tree[pos] += val;
pos += lowbit(pos);
}
}
ll query(ll *tree, int pos)
{
ll sum = 0;
while(pos)
{
sum += tree[pos];
pos -= lowbit(pos);
}
return sum;
}
int main(void)
{
int n, k;
while(cin >> n)
{
memset(tree_num, 0, sizeof(tree_num));
memset(tree_dis, 0, sizeof(tree_dis));
for(int i = 0; i < n; i++)
scanf("%d%d", &a[i].x, &a[i].h);
//
sort(a, a+n, cmp1);
k = 2;
a[0].rx = 1;
for(int i = 1; i < n; i++, k++)
if(a[i].x == a[i-1].x) a[i].rx = a[i-1].rx;
else a[i].rx = k;
//
sort(a, a+n, cmp2);
a[0].rh = 1;
k = 2;
for(int i = 1; i < n; i++, k++)
if(a[i].h == a[i-1].h) a[i].rh = a[i-1].rh;
else a[i].rh = k;
//
sort(a, a+n, cmp);
ll ans = 0;
for(int i = 0; i < n; i++)
{
ll lnum = query(tree_num, a[i].rx-1);
ll rnum = i-query(tree_num, a[i].rx);
ll lsum = query(tree_dis, a[i].rx-1);
ll rsum = query(tree_dis, maxn-1)-query(tree_dis, a[i].rx);
ans += a[i].rh*((lnum*a[i].rx-lsum)+(rsum-rnum*a[i].rx));
update(tree_num, a[i].rx, 1);
update(tree_dis, a[i].rx, a[i].rx);
}
printf("%lld\n", ans);
}
return 0;
}