F. Moving Points
思路:
初中的“追及问题”
假设 Xi 在 Xj 的左侧,并且速度 Vi 大于 Vj,那么 Xi 肯定可以追上 Xj 即 d(i,j) = 0
如果速度 Vi <= Vj ,那么 d(i,j) = abs(Xi - Xj)
所以答案就是:
ans+=(数组中位于当前点前面的点的数量(速度小于当前点速度的点的数量)×当前点的位置)- 前面所有点的位置值的和。
我们可以维护速度 V 的序列,然后每次去查询、更新每个点的贡献
这题还需要注意速度 V 需要进行离散化
#include <algorithm> #include <string> #include <string.h> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <math.h> #include <cstdio> #include <iomanip> #include <time.h> #include <bitset> #include <cmath> #include <sstream> #include <iostream> #define LL long long #define INF 0x3f3f3f3f #define ls nod<<1 #define rs (nod<<1)+1 const double eps = 1e-10; const int maxn = 2e5 + 10;; const LL mod = 1e9 + 7; int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;} using namespace std; int b[maxn]; struct node { int x,v; }a[maxn]; bool cmp(node t1,node t2) { return t1.x<t2.x; } struct segment_tree { LL val,num; }tree[maxn << 2]; void modify(int l,int r,int k,LL v,int nod) { if (l == r) { tree[nod].val += v; tree[nod].num += 1; return ; } int mid = (l + r) >> 1; if (k <= mid) modify(l,mid,k,v,ls); else modify(mid+1,r,k,v,rs); tree[nod].val = (tree[ls].val + tree[rs].val); tree[nod].num = (tree[ls].num + tree[rs].num); } LL query(int l,int r,int ql,int qr,int nod) { if (ql <= l && qr >= r) return tree[nod].val; int mid = (l + r ) >> 1; LL ans = 0; if (ql <= mid) ans += query(l,mid,ql,qr,ls); if (qr > mid) ans += query(mid+1,r,ql,qr,rs); return ans; } LL query2(int l,int r,int ql,int qr,int nod) { if (ql <= l && qr >= r) return tree[nod].num; int mid = (l + r ) >> 1; LL ans = 0; if (ql <= mid) ans += query2(l,mid,ql,qr,ls); if (qr > mid) ans += query2(mid+1,r,ql,qr,rs); return ans; } int main() { int n; 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 len=unique(b+1,b+1+n)-b-1; LL ans=0; for(int i=1;i<=n;i++){ int v = lower_bound(b+1,b+1+len,a[i].v)-b; //cout << query2(1,n,1,v,1) << " " << query(1,n,1,v,1) << endl; ans += query2(1,n,1,v,1)*a[i].x-query(1,n,1,v,1); modify(1,n,v,a[i].x,1); } printf("%lld\n",ans); return 0; }