题解 P2345 【奶牛集会】

YoungNeal

2018-07-18 21:40:48

Solution

## Solution 看到楼下大佬们的log级数据结构表示并不会,我只会暴力数据结构,于是我用分块过了这题。 首先将所有奶牛按照坐标升序排序,并假设我们已经求出每个奶牛到前面所有奶牛的距离和存进了qzh数组。 考虑这个性质:当前扫到了奶牛i,那么奶牛i的贡献至少是$v[i]\times qzh[i]$,称这个为基础贡献。 所以我们不妨对所有奶牛先求出基础贡献,然后再在之后扫描一遍用奶牛i前面的v值比它大的奶牛j来更新一下答案,设答案为ans,也就是 $ans+=(v[j]-v[i])\times (x[i]-x[j])$ 。 展开这个式子, $v[j]\times x[i]-v[j]\times x[j]-v[i]\times x[i]+v[i]\times x[j]$。 发现这几项都可以用前缀和维护,就做完了。 用分块只是为了平衡一下时间复杂度 ## Code ```cpp #include<cmath> #include<cstdio> #include<cctype> #include<vector> #include<algorithm> #define N 20005 #define int long long #define min(A,B) ((A)<(B)?(A):(B)) #define max(A,B) ((A)>(B)?(A):(B)) #define swap(A,B) ((A)^=(B)^=(A)^=(B)) int n,ans; int qzh[N]; int belong[N]; int block,l[N],r[N]; int vx[204][N],v[204][N],x[204][N]; struct Node{ int a,b; }node[N]; bool cmp(Node x,Node y){ return x.a<y.a; } bool cmp2(Node x,Node y){ return x.b<y.b; } int getint(){ int x=0,f=0;char ch=getchar(); while(!isdigit(ch)) f|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return x; } void write(int x){ if(x>9) write(x/10); putchar(x%10+'0'); } void init(int y){ std::sort(node+l[y],node+r[y]+1,cmp2); vx[y][l[y]]=node[l[y]].a*node[l[y]].b; v[y][l[y]]=node[l[y]].b; x[y][l[y]]=node[l[y]].a; for(int i=l[y]+1;i<=r[y];i++){ vx[y][i]=vx[y][i-1]+node[i].a*node[i].b; v[y][i]=v[y][i-1]+node[i].b; x[y][i]=x[y][i-1]+node[i].a; } } int bsearch(int l,int r,int p){ int ans=0; while(l<=r){ int mid=l+r>>1; if(node[mid].b>p) ans=mid,r=mid-1; else l=mid+1; } return ans; } signed main(){ n=getint(); block=sqrt(n); for(int i=1;i<=n;i++){ belong[i]=(i-1)/block+1; node[i].b=getint(); node[i].a=getint(); } int tot=n/block+(n%block?1:0); for(int i=1;i<=tot;i++){ l[i]=(i-1)*block+1; r[i]=i*block; } r[belong[n]]=n; std::sort(node+1,node+1+n,cmp); for(int i=2;i<=n;i++) qzh[i]=qzh[i-1]+(node[i].a-node[i-1].a)*(i-1),ans+=node[i].b*qzh[i]; for(int i=2;i<=n;i++){ if(belong[i]!=belong[i-1]) init(belong[i-1]); for(int j=1;j<belong[i];j++){ int p=bsearch(l[j],r[j],node[i].b); if(!p) continue; p--; int q=node[i].a*(v[j][r[j]]-v[j][p])-vx[j][r[j]]+vx[j][p]+node[i].b*(x[j][r[j]]-x[j][p])-(r[j]-p)*node[i].a*node[i].b; ans+=q; } for(int j=l[belong[i]];j<i;j++){ if(node[j].b>node[i].b) ans+=node[i].a*node[j].b-node[j].b*node[j].a+node[i].b*node[j].a-node[i].a*node[i].b; } } printf("%lld\n",ans); return 0; } ```