zoukankan      html  css  js  c++  java
  • 【CodeForces 1311F】Moving Points

    链接:

    洛谷

    博客园

    题目大意:

    一条数轴上有 (n) 个动点,每个动点的初始坐标是 (x_i),它们每秒会向右移 (v_i)。求出所有点对最短距离之和。

    正文:

    假设我们当前正在处理点对 ((i,j))。如果 (v_i<v_j)

    那么它们的距离会越来越远,所以初始距离则是最短距离。


    如果 (v_i=v_j)

    那么它们的距离不会改变,初始距离还是最短距离。


    如果 (v_i>v_j)

    因为时间不一定是整数,所以它们必然会走到一个点,即距离为 (0)

    那么现在可以把题目转换成:(x_i<x_j)(v_ileq v_j) 的点对距离和。显然是二维偏序。维护两个树状数组 (A,B),分别维护的是已经维护了点的数量、已维护点到原点距离之和。那么答案是 (sum Acdot x_i-B)

    代码:

    const int N = 2e5 + 10;
    
    ll t[2][N], b[N];
    int n, m;
    ll ans;
    
    void modify(int x, ll val, ll t[]){for (; x <= N - 10; x += x & -x) t[x] += val;}
    ll query (int x, ll t[])
    {
    	ll ans = 0;
    	for (; x; x -= x & -x) ans += t[x];
    	return ans;
    }
    
    struct node
    {
    	int x, v;
    }a[N];
    
    bool cmp (node a, node b) {return a.x < b.x || (a.x == b.x && a.v < b.v);}
    
    int main ()
    {
    	scanf ("%d", &n);
    	for (int i = 1; i <= n; i++)
    		scanf ("%d", &a[i].x);
    	for (int i = 1; i <= n; i++)
    		scanf ("%d", &a[i].v), b[i] = a[i].v;
    	sort (a + 1, a + 1 + n, cmp);
    	sort (b + 1, b + 1 + n);
    	int k = unique(b + 1, b + 1 + n) - b;
    	for (int i = 1; i <= n; i++)
    		a[i].v = lower_bound(b + 1, b + 1 + k, a[i].v) - b;
    	for (int i = 1; i <= n; i++)
    	{
    		modify(a[i].v, a[i].x, t[0]);
    		modify(a[i].v, 1, t[1]);
    		ans += query(a[i].v, t[1]) * a[i].x - query(a[i].v, t[0]);
    	}
    	printf ("%lld
    ", ans);
    	
    	return 0;
    }
    
    
  • 相关阅读:
    poj 1584
    poj 1113 & poj 2187
    pku 1321 棋盘问题
    poj 1408
    pku 2251 Dungeon Master
    sdut oj 2218 Give Me an E
    Android工程 单元测试
    Android Timer编写方式
    去除工程的.svn隐藏文件夹
    Android 绑定远程服务出现 Not Allowed to bind service
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14450368.html
Copyright © 2011-2022 走看看