学习笔记
Cdq分治
其实这一个是对于多维数据的一个分治,我们用二维为例子,我们先将一维进行排序,之后我们对第二维进行分治时候,我们就可以保证前面的第一位度一定小于后面二第一维度,然后就用第二维度去进行答案的累加就OK了
例题来一道奶牛,一看到奶牛就知道是ACM的题了吧,描述就不加了,主要是思路虽然说这道题的数据如果打暴力也可以做出来,但是毕竟要不断进步,我们发现他的求和不仅有max又有绝对值,所以说我们没有办法直接分治,那么我们呢就可以用cdq分治,先排序声音,之后就只用对路程分治就欧克了。
代码如下
#include<bits/stdc++.h>
using namespace std;
int n;
struct nai{
long long x;long long v;
};
nai a[20004];
bool cmp(nai y,nai z){
return y.v<z.v;
}
long long ans=0;
nai q[20005];
void f(int l,int r){
if(l>=r) return;
int mid=(l+r)/2;
f(l,mid);
f(mid+1,r);
long long lcnt=0,rcnt=mid-l+1;
long long lsum=0,rsum=0;
int lhead=l,rhead=mid+1;
for(int i=l;i<=mid;i++){rsum+=a[i].x;}
for(int i=l;i<=r;i++){
if(rhead<=r&&(lhead>mid||a[rhead].x<a[lhead].x)){//左边大我们就放右边的,并且通过标记来去除绝对值
ans+=(lcnt*a[rhead].x-lsum)*a[rhead].v;
ans+=(rsum-a[rhead].x*rcnt)*a[rhead].v;
q[i]=a[rhead];
rhead++;
}
else{
lcnt++;
rcnt--;
lsum+=a[lhead].x;
rsum-=a[lhead].x;
q[i]=a[lhead];
lhead++;
}
}
for(int i=l;i<=r;i++) a[i]=q[i];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld%lld",&a[i].v,&a[i].x);
}
sort(a+1,a+1+n,cmp);
f(1,n);
printf("%lld",ans);
return 0;
}