zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    描述一下 JVM 加载 class 文件的原理机制?
    Java 中会存在内存泄漏吗,请简单描述
    关于同步机制的一些见解
    Mybatis 一对一,一对多,多对一,多对多的理解
    关于JavaBean实现Serializable接口的见解
    Python 文件I/O
    Python 模块
    Python 函数
    Python time tzset()方法
    Python time time()方法
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12380369.html
Copyright © 2011-2022 走看看