http://acm.hdu.edu.cn/showproblem.php?pid=3015
【题意】
有一些高度和位置的树,先将高度和位置分别排序得到rank
任意两个两棵树的值为min(高度)*abs(位置差),问所有任意两棵树的差为多少
【代码】
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll maxn = 1e5 + 5;
struct node {
ll x, h, id;
}p[maxn], pp[maxn];
ll c[2][maxn];
int cmp1(node a, node b) {
return a.x < b.x;
}
int cmp2(node a, node b) {
return a.h < b.h;
}
int cmp(node a, node b) {
return a.h > b.h;
}
ll lowbit(ll x) {
return x & (-x);
}
void add(ll i, ll j, ll x) {
while (i <= maxn) {
c[j][i] += x;
i += lowbit(i);
}
}
ll query(ll x,ll j) {
ll res = 0;
while (x>0) {
res += c[j][x];
x -= lowbit(x);
}
return res;
}
int main() {
ll n;
while (~scanf("%lld", &n)) {
memset(c, 0, sizeof(c));
for (ll i = 1; i <= n; i++) {
scanf("%lld%lld", &p[i].x, &p[i].h);
p[i].id = i;
pp[i] = p[i];
}
sort(pp + 1, pp + 1 + n, cmp1);
for (ll i = 1; i <= n; i++) {
if (i>1&&pp[i].x == pp[i - 1].x) {
p[pp[i].id].x = p[pp[i - 1].id].x;
}
else {
p[pp[i].id].x = i;
}
}
sort(pp + 1, pp + 1 + n, cmp2);
for (ll i = 1; i <= n; i++) {
if (i>1&&pp[i].h == pp[i - 1].h) {
p[pp[i].id].h = p[pp[i - 1].id].h;
}
else {
p[pp[i].id].h = i;
}
}
sort(p + 1, p + 1 + n, cmp);
add(p[1].x, 0, 1);
add(p[1].x, 1, p[1].x);
ll sumx = p[1].x;
ll ans = 0;
//
for (ll i = 2; i <= n; i++) {
ll cnt = query(p[i].x - 1, 0);
ll sum = query(p[i].x - 1, 1);
ll cnt1 = i - 1 - query(p[i].x, 0);
ll sum1 = sumx - query(p[i].x, 1);
ans += p[i].h*(p[i].x*(cnt - cnt1) - sum + sum1);
add(p[i].x, 0, 1);
add(p[i].x, 1, p[i].x);
sumx += p[i].x;
}
printf("%lld\n", ans);
}
}