/* 纯属参考 : http://hi.baidu.com/forverlin1204/blog/item/98cb564dcdcc25f5d62afc61.html 树状数组 题目描述:给定一个长为n的序列,元素有两个属性x,h(x代表坐标,h代表高度) 求任意点(i,j)对的不调和值之和,不调和值有两部分组成F和S F是指i和j的x坐标(离散化后)差的绝对值F=abs(x[i]-x[j]) S是指i和j的高度(离散化后)S=min(h[i],h[j]),这两者之积F*S就是(i,j)不可调和值 分析:我们首先按高度从大到小排序,然后来统计这样我们解决了高度最小的问题 对于在i位置的元素,我们统计高度比h[i]大x比当x值小的x坐标和,同时统计高度比h[i]大,但坐标比x小的个数 num=sum|x[i]-y[j]|*h[i](j<i) 设query1(x)查询比x小的个数,query2(x)查询比x小的x和 等价于a*x[i]-sum1+sum2-b*x[i] 其中a表示比当前点x小的点数,b表示比当前点x大的点数,sum1表示比当前点x小的x和,sum2表示比当前点x大的x和 可以表示成a=query1(x[i]-1),b=query1(n)-query1(x[i]),sum1=query2(x[i]-1),sum2=query2(n)-query2(x[i]) 得ans=query(x[i]-1)*x[i]-query2(x[i]-1)+query2(n)-query2(x[i])-(query1(n)-query1(x[i]))*x[i] 然后ans*=h[i],这就是当前项做为h最小的贡献量 */ #include <iostream> #include <cstdio> #include <algorithm> #define lowbit(x) (x & (-x)) using namespace std; const int N = 100005; //typedef long long LL; typedef __int64 LL; struct Node{ int x, h; } node[N]; int n; LL sum[2][N]; bool readint(int &ret){ int sgn; char c; c = getchar(); if(c == EOF ) return true; while(c != '-' && c < '0' || c > '9') c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return false; } void Init(int n){ for(int i = 0; i <= n; i++) sum[0][i] = sum[1][i] = 0; } void Add(int x, int val, int flag){ while(x <= n){ sum[flag][x] += val; x += lowbit(x); } } LL Query(int x, int flag){ LL ans = 0; while(x > 0){ ans += sum[flag][x]; x -= lowbit(x); } return ans; } bool cmpx(const Node &a, const Node &b){return a.x < b.x;} bool cmph1(const Node &a, const Node &b){return a.h < b.h;} bool cmph2(const Node &a, const Node &b){return a.h > b.h;} int main(){ while(scanf("%d", &n) != EOF){ for(int i = 0; i < n; i++){ //scanf("%d %d", &node[i].x, &node[i].h); readint(node[i].x); readint(node[i].h); } sort(node, node + n, cmpx); for(int i = 0; i < n; i++){ // x排名 int temp = node[i].x; int j = i + 1; node[i].x = i + 1; while(temp == node[j].x && j < n){ node[j].x = i + 1; j++; } i = j - 1; } sort(node, node + n, cmph1); for(int i = 0; i < n; i++){ // h 排名 int temp = node[i].h; int j = i + 1; node[i].h = i + 1; while(temp == node[j].h && j < n){ node[j].h = i + 1; j++; } i = j - 1; } sort(node, node + n, cmph2); // 高度大到小 LL ans = 0; Init(n); for(int i = 0; i < n; i++){ Add(node[i].x, 1, 0); Add(node[i].x, node[i].x, 1); int a = Query(node[i].x- 1, 0); int b = Query(n, 0) - Query(node[i].x, 0); LL sum1 = Query(node[i].x - 1, 1); LL sum2 = Query(n, 1) - Query(node[i].x, 1); ans += (a * node[i].x - sum1 + sum2 - b * node[i].x) * node[i].h; } printf("%I64d/n", ans); } }