Codeforces 903D Almost Difference
Let‘s denote a function
You are given an array a consisting of n integers. You have to calculate the sum of d(ai,?aj) over all pairs (i,?j) such that 1?≤?i?≤?j?≤?n.
The first line contains one integer n (1?≤?n?≤?200000) — the number of elements in a.
The second line contains n integers a1, a2, ..., an (1?≤?ai?≤?109) — elements of the array.
Print one integer — the sum of d(ai,?aj) over all pairs (i,?j) such that 1?≤?i?≤?j?≤?n.
5
1 2 3 1 3
4
4
6 6 5 5
0
4
6 6 4 4
-8
In the first example:
- d(a1,?a2)?=?0;
- d(a1,?a3)?=?2;
- d(a1,?a4)?=?0;
- d(a1,?a5)?=?2;
- d(a2,?a3)?=?0;
- d(a2,?a4)?=?0;
- d(a2,?a5)?=?0;
- d(a3,?a4)?=??-?2;
- d(a3,?a5)?=?0;
- d(a4,?a5)?=?2.
分析:刚拿到这题,先想到的是:归并排序,仔细构思了一下感觉细节很多,不大好写;转而去想线段树(归并排序能解决的线段树都行),绝对值差在1及以内的直接不考虑就行了,那么对于一个值x,要考虑的区间范围是[1,x-2]U[x+2,+inf],这样先离散化,然后线段树维护离散化后的下标,维护的信息有两个:区间和与区间计数(sum和cnt),因为对于x的查询结果sum和cnt,ans=cnt*x-sum,然后就是基本的单点更新,区间查询了。这道题要用高精度,我偷懒没写。主要原因是这道题其实用不着线段树,只要set或者map维护一下集合,然后维护前缀和即可。。这样写主程序代码长度不超过50行,比我100行的线段树代码清爽多了。