Codeforces Round #624 (Div. 3) 比赛人数6075
[codeforces 1311F] Moving Points 离散化+树状数组
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址https://codeforces.ml/contest/1311/problem/F
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
F - Moving Points | GNU C++11 | Accepted | 156 ms | 5300 KB |
//题意总归是理解了
/*
3
1 3 2
-100 2 3
3
d(1,2)=3-1=2,d(1,3)=2-1=1,d(2,3)=0
*/
//如果是O(n^2)的算法,该题比较简单,就是一个简单枚举
//从数据范围看,该题象是O(nlogn)
/*
想了想
xi+vi*t=xj+vj*t
t=(xi-xj)/(vj-vi)
特判vj=vi,d(i,j)=abs(xi-xj)
若t>=0,d(i,j)=0
若t<0,d(i,j)=abs(xi-xj)
算法如下
xi<xj,按坐标自小到大排序
vj-vi>=0 => vi<=vj ans+=abs(xi-xj)
树状数组
*/
//编写过程中,若相关函数不熟悉,记得及时测试。
//发现该题改编自2013 ACM/ICPC Asia Regional Online —— Warmup2
//改编后,难度有较大提升。
// (1≤xi≤10^8),(2≤n≤2⋅10^5).10^8*10^5=10^13 int溢出
STL之unique()去重函数
STL之lower_bound,upper_bound二分查找函数
看了比赛时提交的AC代码,离散化部分,清一色的如下面的代码,请读者重点掌握该离散化代码。
#include <cstdio>
#include <algorithm>
#define maxn 200010
#define LL long long
using namespace std;
struct node{
int loc,v;
}a[maxn];
int n,m,b[maxn];
LL c[maxn],e[maxn];
int cmp(node a,node b){
return a.loc<b.loc;
}
int lowbit(int x){
return x&-x;
}
void update(int pos,int delta,LL *d){
for(int i=pos;i<=n;i+=lowbit(i))d[i]+=delta;
}
LL sum(int pos,LL *d){
LL ret=0;
for(int i=pos;i>0;i-=lowbit(i))ret+=d[i];
return ret;
}
int main(){
int i;
LL ans=0;
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i].loc);
for(i=1;i<=n;i++)scanf("%d",&a[i].v),b[i]=a[i].v;
sort(b+1,b+1+n);//离散化开始
m=unique(b+1,b+1+n)-(b+1);
for(i=1;i<=n;i++)a[i].v=lower_bound(b+1,b+1+m,a[i].v)-b;//离散化结束
sort(a+1,a+1+n,cmp);
for(i=1;i<=n;i++){
ans+=abs(sum(a[i].v,e)-sum(a[i].v,c)*a[i].loc);//sum(a[i].v,c)统计比vi小的点数量,sum(a[i].v,e)统计比vi小的点坐标和
update(a[i].v,1,c),update(a[i].v,a[i].loc,e);
}
printf("%lld\n",ans);
return 0;
}