树状数组练习 POJ-1990

 题目链接

 求一个点到另外点的距离不用dis[i]-dis[j]

可以先求出其他点的个,其他点的个数  ,dis[i] * num - sum即为所求

用两个数组数来维护num和sum

#include 
#include 
#include 

using namespace std;

#define N 20010
struct node
{
    int v, x;
    friend bool operator < (node x, node y)
    {
        if (x.v == y.v)
        {
            return x.x < y.x;
        }
        return x.v < y.v;
    }
} a[N];

int lowbit(int x)
{
    return x & -x;
}

long long getsum(long long *t, int k)
{
    long long sum = 0;
    while (k)
    {
        sum += t[k];
        k -= lowbit(k);
    }
    return sum;
}

void update(long long *t, int k, int data)
{
    while (k <= N)
    {
        t[k] += (long long)data;
        k += lowbit(k);
    }
}

long long num[N], sum[N];

int main()
{
    int n;
    scanf("%d", &n);
    
    for (int i = 0; i < n; ++i)
    {
        scanf("%d%d", &a[i].v, &a[i].x);
    }
    
    sort(a, a + n);
    memset(num, 0, sizeof(num));
    memset(sum, 0, sizeof(sum));
    
    long long ans = 0;
    for (int i = 0; i < n; ++i)
    {
        long long nm = getsum(num, a[i].x);
        long long sm = getsum(sum, a[i].x);
        long long sm2 = getsum(sum, N);
        
        ans += (nm * a[i].x - sm + sm2 - sm - (i - nm) * a[i].x) * a[i].v;
        
        update(sum, a[i].x, a[i].x);
        update(num, a[i].x, 1);
    }
    
    printf("%lld\n", ans);
    
    return 0;
}

 

你可能感兴趣的:(算法练习)