Codeforces1311F. Moving Points (树状数组 离散化)

https://codeforces.com/problemset/problem/1311/E

 

   题目点对追击问题可以抽象成两个一次函数相交问题,y = v*t+xi,xi为y轴上的截距,v是斜率,那么当且仅当两个函数在第一象限相交时,点对的最小距离是0,如果两个点对不在第一象限相交,则点对最小距离是就是y轴截距绝对值之差。

   可以轻易得到在第一象限相交的条件是,假设直线L1和L2,L1的斜率小于L2的斜率,L1的截距小于L2的截距时,两个直线在第一象限没有交点,其余情况均有交点。分别讨论这两种情况即可。

   首先离散化,把点的移动速度按从小打到排序一遍,并去重,再开一个结构体存贮点对信息,并按照截距大小排序。

   遍历结构体,用两个树状数组维护Vi,和Xi的前缀和,对于P[i]的速度Vi,在speed排序后的数组中查询Vi在speed数组中的位置pos,树状数组查询斜率比P[i]的斜率小的点个数,查询pos位置点的截距之和,那么P[i]对于答案的贡献就是:斜率比P[i]的斜率小的点个数×Xi(截距)- 斜率比P[i]小且截距比P[i]小的点的截距之和,每次把其贡献加入答案之后,在树状数组中去更新pos位置的点个数和和前缀和。

 

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 2e5+5;
 5 int n;
 6 ll c[maxn],c2[maxn]; 
 7 int lowbit(int x) {
 8   return x & -x;
 9 }
10 void add(ll x, ll k) {
11   while (x <= n) { 
12     c[x] = c[x] + k;
13     x = x + lowbit(x);
14   }
15 }
16 void add2(ll x, ll k) {
17   while (x <= n) { 
18     c2[x] = c2[x] + k;
19     x = x + lowbit(x);
20   }
21 }
22 ll getsum(int x) {  
23   ll ans = 0;
24   while (x >= 1) {
25     ans = ans + c[x];
26     x = x - lowbit(x);
27   }
28   return ans;
29 }
30 ll getsum2(int x){
31     ll ans = 0;
32    while (x >= 1) {
33      ans = ans + c2[x];
34      x = x - lowbit(x);
35   }
36   return ans;
37 }
38 struct node{
39     ll x,v;
40     bool operator < (const node &b) const{
41         return x<b.x ;
42     }
43 }p[maxn];
44 map<ll,int> m;
45 vector<int> speed;
46 int main(){
47     scanf("%d",&n);
48     for(int i = 1;i<=n;i++){
49         ll x;scanf("%lld",&x);
50         p[i].x = x;
51     }
52     for(int i = 1;i<=n;i++){
53         ll v;scanf("%lld",&v);
54         p[i].v = v;
55         if(m[v] == 0) m[v] = 1,speed.push_back(v);
56     }
57     ll ans = 0;
58     sort(p+1,p+1+n);
59     sort(speed.begin(),speed.end());
60     for(int i = 1;i<=n;i++){
61         ll cur = p[i].v;
62         int pos = upper_bound(speed.begin(),speed.end(),cur) - speed.begin();
63         ll sum = getsum(pos),cnt = getsum2(pos);
64         ans+=p[i].x*(cnt) - sum;
65         add(pos,p[i].x),add2(pos,1);
66     }
67     cout<<ans;
68     return 0;
69 }
View Code

 

posted @ 2020-02-28 21:33  AaronChang  阅读(191)  评论(0编辑  收藏  举报