题意:
给出n的质点,带着初位置和速度;
如果中途两点可以相遇dis(i,j)=0;
如果不可以相遇,mindis(i,j);
求n个点的两两质点最小dis(i,j)之和
思路:
因为当初位置x和速度v都比另一个小的时候,他们才不会相遇,所以最小的初位置想减也是abs(xi-xj)
因为速度-10^8<=v<=10^8的范围,需要离散化
将初位置进行从小到大排序,进行循环,他的速度(设v1)在所有速度的哪个位置(设pos),x1代表v1这个初始值
那么在这个位置pos之前的树状数组里存着的也是比x1小的初位置的值,用cnt[][0]存比x1小同时比v1小的点有几个,用cnt[][1]存比x1小同时比v1小的点初始值之和
每个点(初始值从小到大)的贡献x1*get(pos,0)-get(pos,1);
扫描二维码关注公众号,回复:
9407157 查看本文章
最后存add(pos,x1)
树状数组1~n存的是离散化后的速度,相当于从小到大进行1~ni编号。中间可能有重复ni可能小于n
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define il inline 5 #define it register int 6 #define inf 0x3f3f3f3f 7 #define lowbit(x) (x)&(-x) 8 #define mem(a,b) memset(a,b,sizeof(a)) 9 #define mod 998244353 10 const int maxn=2e5+10; 11 int n,t,m; 12 struct node{ 13 int x,v; 14 friend bool operator<(const node a,const node b){ 15 if(a.x==b.x){ 16 return a.v<b.v; 17 } 18 return a.x<b.x; 19 } 20 }a[maxn]; 21 int v[maxn]; 22 ll cnt[maxn][2]; 23 il void add(int x,int val){ 24 for(it i=x;i<=n;i+=lowbit(i)){ 25 cnt[i][0]++; 26 cnt[i][1]+=(ll)val; 27 } 28 return ; 29 } 30 il ll get(int x,int k){ 31 ll sum=0; 32 while(x){ 33 sum+=cnt[x][k]; 34 x-=lowbit(x); 35 } 36 return sum; 37 } 38 int main(){ 39 scanf("%d",&n); 40 for(it i=0;i<n;i++){ 41 scanf("%d",&a[i].x); 42 } 43 for(it i=0;i<n;i++){ 44 scanf("%d",&a[i].v); 45 v[i]=a[i].v; 46 } 47 sort(a,a+n);sort(v,v+n); 48 ll ans=0; 49 for(it i=0;i<n;i++){ 50 int pos=upper_bound(v,v+n,a[i].v)-v; 51 ans+=(ll)a[i].x*get(pos,0)-get(pos,1); 52 add(pos,a[i].x); 53 } 54 printf("%lld\n",ans); 55 return 0; 56 }
这场让我上了蓝,但不得不说降智场,D题在用bfs做,写了整整一个半小时,然后wa,后面其实都能做但就是比赛的时候不敢,也容易慌
这场前三题半小时不到就完成了,然后看到F比E过的还多,瞄了一眼F,想了想把速度从1~n编码就又去想D了。然后想歪了