https://www.luogu.org/problem/show?pid=2657
题目描述
一群青年人排成一队,用手机互相聊天。
每个人的手机有一个信号接收指标,第i个人的接收指标设为v[i]。
如果位置在x[i]的人要和位置在xj的人聊天,那么这两人组成的一对的信号发射强度就是abs(x[i]-x[j])*max(v[i],v[j]).
现在我们想知道,这些人所有对子中的信号发射强度的总和。
输入输出格式
输入格式:
第一行一个整数N,接下来N行,每行两个整数v[i]和x[i]。
输出格式:
所有对的信号发射强度总和。
输入输出样例
输入样例#1:
4 3 1 2 5 2 6 4 3
输出样例#1:
57
说明
对于40%的数据,N<=5,000
对于100%的数据,N<=100,000 1≤x[i]≤20,000
[color=red]注意:可能有两人在同一个位置
答案在int64或long long范围内[/color]
对于公式 abs(x[i]-x[j])*max(v[i],v[j]). 先给年轻人排队,让V小的在前面
用树状数组维护第i个人的前面有多少人的x比他的小,维护前面比他小的x的人的x的总和
1 #include <algorithm> 2 #include <cstdio> 3 4 #define LL long long 5 const int N(100000+5); 6 LL n,ans; 7 struct Node { 8 LL val,pos; 9 bool operator < (const Node &x)const 10 { 11 return val<x.val; 12 } 13 }people[N]; 14 15 inline void read(LL &x) 16 { 17 x=0; register char ch=getchar(); 18 for(;ch>'9'||ch<'0';) ch=getchar(); 19 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 20 } 21 22 #define max(a,b) (a>b?a:b) 23 24 LL maxpos,sum[N],num[N]; 25 #define lowbit(x) (x&((~x)+1)) 26 inline void Update(LL *tr,LL i,LL x) 27 { 28 for(; i<=maxpos; i+=lowbit(i)) tr[i]+=x; 29 } 30 inline LL Query(LL *tr,LL i) 31 { 32 LL ret=0; 33 for(; i; i-=lowbit(i)) ret+=tr[i]; 34 return ret; 35 } 36 37 int AC() 38 { 39 read(n); 40 for(int i=1; i<=n; ++i) 41 { 42 read(people[i].val); 43 read(people[i].pos); 44 maxpos=max(maxpos,people[i].pos); 45 } 46 std::sort(people+1,people+n+1); 47 for(int i=1; i<=n; ++i) 48 { 49 LL pos=people[i].pos,val=people[i].val; 50 LL numl=Query(num,pos-1); 51 LL suml=Query(sum,pos-1); 52 LL numr=Query(num,maxpos)-Query(num,pos); 53 LL sumr=Query(sum,maxpos)-Query(sum,pos); 54 ans+=val*(pos*numl-suml+sumr-pos*numr); 55 Update(num,pos,1); Update(sum,pos,pos); 56 } 57 printf("%lld\n",ans); 58 return 0; 59 } 60 61 int Hope=AC(); 62 int main(){;}