Codeforces Round #624 (Div. 3) F

题意:

给出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);

最后存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 }
View Code

这场让我上了蓝,但不得不说降智场,D题在用bfs做,写了整整一个半小时,然后wa,后面其实都能做但就是比赛的时候不敢,也容易慌

这场前三题半小时不到就完成了,然后看到F比E过的还多,瞄了一眼F,想了想把速度从1~n编码就又去想D了。然后想歪了

猜你喜欢

转载自www.cnblogs.com/luoyugongxi/p/12364540.html