http://poj.org/problem?id=1990
给定 n n n个奶牛,每个奶牛有两个权值,第一个 p o s pos pos表示位置,每个点的 p o s pos pos均不相同,第二个表示 v a l val val表示奶牛声音传播属性,对于两个奶牛 ( x , y ) (x,y) (x,y)之间的交流有一个结果,值等于 ∣ p o s x − p o s y ∣ \left| pos_x-pos_y\right| ∣posx−posy∣ ∗ \ast ∗ m a x ( v a l x , v a l y ) max(val_x,val_y) max(valx,valy),求 ( n − 1 ) n 2 \frac{(n-1)n}{2} 2(n−1)n对奶牛相互交流得到的这个结果的和;
我们首先将奶牛按 v a l val val排序,那么对于奶牛 x x x,(下面说的之前并不是指距离,而是指按 v a l val val排序过后的相对位置);它之前的奶牛 y y y与它交流的 m a x ( v a l x , v a l y ) max(val_x,val_y) max(valx,valy)均等于 v a l x val_x valx,这时候我们对于每个奶牛 x x x,只需要计算它与它之前奶牛的距离 p o s pos pos的绝对值的和即可,那么如何计算 ∣ p o s x − p o s y ∣ \left| pos_x-pos_y\right| ∣posx−posy∣呢;
对于每个奶牛 x x x之前的奶牛 y y y和 x x x的距离有两种可能,要么 p o s x > p o s y pos_x>pos_y posx>posy,要么 p o s x < p o s y pos_x<pos_y posx<posy;我们用 d i s > dis_> dis>代表位于 x x x之前的满足 p o s x < p o s y pos_x<pos_y posx<posy的所有 p o s y pos_y posy和即( ∑ p o s y \sum pos_y ∑posy),同样有 d i s < dis_< dis<代表位于 x x x之前的满足 p o s x > p o s y pos_x>pos_y posx>posy的所有 p o s y pos_y posy和即( ∑ p o s y \sum pos_y ∑posy),又有 n u m > num_> num>,代表 p o s x > p o s y pos_x>pos_y posx>posy的 y y y的个数,有 n u m < num_< num<,代表 p o s x < p o s y pos_x<pos_y posx<posy的 y y y的个数,那么有对于每个奶牛只要计算 ∑ i = 1 n v a l i ∗ ( n u m < ∗ p o s x − d i s < + d i s > − n u m > ∗ p o s x ) \sum_{i=1}^n val_i\ast(num_<\ast pos_x-dis_<+dis_>-num_>\ast pos_x) ∑i=1nvali∗(num<∗posx−dis<+dis>−num>∗posx),这就是我们需要的答案, n u m num num和 d i s dis dis用两个树状数组求即可;
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define inf 0x7f7f7f7f
#define maxn 16041
#define N 2
#define mod 100003
typedef long long ll;
typedef struct {
int u, v, next, w;
} Edge;
Edge e[N];
int cnt, head[N];
inline void add(int u, int v) {
e[cnt].u = u;
e[cnt].v = v;
//e[cnt].w=w;
// e[cnt].f=f;
e[cnt].next = head[u];
head[u] = cnt++;
//e[cnt].u=v;
// e[cnt].v=u;
// e[cnt].w=0;
// e[cnt].f=-f;
// e[cnt].next=head[v];
// head[v]=cnt++;
}
inline void write(int x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
inline int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
struct cow {
ll pos, val;
};
bool compare(cow a, cow b) {
return a.val < b.val;
}
cow c[22000];
ll maxm,n, dis[20200], cot[20200];
void insert(ll x, ll t[], ll val) {
while (x <= 20040) {
t[x] += val;
x += x & -x;
}
}
ll sum(ll x,ll t[]){
ll res=0;
while(x){
res+=t[x];
x-=x&-x;
}
return res;
}
int main() {
while (cin >> n) {
memset(dis,0,sizeof(dis));
memset(cot,0,sizeof(cot));
for (int i = 1; i <= n; i++) {
scanf("%lld%lld", &c[i].val, &c[i].pos);
}
sort(c + 1, c + 1 + n, compare);
ll ans = 0;
ll did=0,dix=0,nud=0,nux=0;
for (int i = 1; i <= n; i++) {
dix=sum(c[i].pos,dis);
did=sum(20040,dis)-dix;
nux=sum(c[i].pos,cot);
nud=sum(20040,cot)-nux;
insert(c[i].pos,cot,1);
insert(c[i].pos,dis,c[i].pos);
ans+=c[i].val*(nux*c[i].pos-dix);
ans+=c[i].val*(did-nud*c[i].pos);
}
cout<<ans<<endl;
}
return 0;
}
我们坚持一件事情,并不是因为这样做了会有效果,而是坚信,这样做是对的。
——哈维尔