分治算法
基本思想:将序列分为 \([l,mid]\) 和 \([mid+1,r]\),然后递归两边,同时再计算 \([l,mid]\) 与 \([mid+1,r]\) 影响所产生的答案(满足单调性的话一般使用走指针)。
二维偏序
首先将所有元素按 \(x,y\) 排序。
然后递归两边,随后用两个指针 \(i\) 和 \(j\),\(i\) 从 \(l\) 到 \(mid\),\(j\) 从 \(mid+1\) 到 \(r\),当 \(y_i>y_j\),说明 \(l\sim i-1\) 的点都不超过 \(j\),于是 \(ans_j\) 累加 \(i-l\),然后 \(j\) 后移一位;如果不是,那么我们的 \(i\) 往后移动一位。
这么做会有一个问题,我们的两边都应该按 \(y\) 排序,才能满足 \(y\) 的单调性,然而我们却按 \(x\) 排序,所以在统计完后重构 \(l\sim r\) 即可。
void f(int l,int r){
if(l==r) return ;
int m=(l+r)/2,i=l,j=m+1,c=l;
f(l,m);f(m+1,r);
while(i<=m||j<=r){
if(j>r||(i<=m&&a[i].y<=a[j].y))
b[c++]=a[i++];//类似于归并排序
else ans[a[j].id]+=i-l,b[c++]=a[j++];
}
for(int i=l;i<=r;i++)a[i]=b[i];
}
平面最近点对
计算 \([l,mid]\) 到 \([r,mid]\) 的最小点对,假设 \(d=\min(calc(l,mid),calc(mid+1,r))\)。
首先先排除离 \(mid\) 距离大于 \(d\) 的点,这些点肯定不会更优。
然后把这些点按 \(y\) 排序,依次枚举所有点对,注意要判如果 \(y\) 轴差已经大于最优答案就跳出循环。
double merge(int left, int right)
{
double d = INF;
if(left == right) return d;
if(left + 1 == right) return dist(left, right);
int mid = left + right >> 1;
double d1 = merge(left, mid);
double d2 = merge(mid + 1, right);
d = min(d1, d2);
int i, j, k = 0;
for(i = left; i <= right; i++)
if(fabs(S[mid].x - S[i].x) < d)
temp[k++] = i;
sort(temp, temp + k, cmps);
for(i = 0; i < k; i++)
for(j = i + 1; j < k && S[temp[j]].y - S[temp[i]].y < d; j++)
{
double d3 = dist(temp[i], temp[j]);
if(d > d3) d = d3;
}
return d;
}
渔网
考虑鱼 \([t,x]\)(在 \(t\) 时刻出现在 \(x\) 的鱼) 如果被网 \([T,y]\) (在 \(T\) 时刻撒在 \(y\) 的网)给网住,那应该满足什么条件。
在 \(t\) 时刻,网会蔓延 \(t-T\) 秒,那么其包含的便是 \([y-(t-T),y+(t-T)]\)。鱼被网住则 \(y-(t-T)\le x\le y+(t-T)\)。
\(y-t+T\le x\) 且 \(x\le y+t-T\)
\(y+T\le x+t\) 且 \(x-t\le y-T\)(即 \(t-x\ge T-y\))
考虑新定义鱼的二元组 \((t-x,t+x)\) 与网的二元组 \((T-y,T+y)\),题目则问每个网的二元组 \((a,b)\) 有多少鱼的二元组 \((x,y)\) 满足 \(a\le x,b\le y\),二位偏序问题分治即可。
总结
当我们想对于每个 \(i\),都算出 \(\sum_{j<i\text{且}can(j,i)==true}giv(j)\):
void sol(int l,int r){
if(l>=r)return ;
int mid=l+r>>1;
sol(l,mid);sol(mid+1,r);
int ct=l,sum=0;
for(int i=l,j=mid+1;i<=mid||j<=r;){
if(i>mid||(j<=r&&can(i,j)==false))cnt1[p[j].id]+=sum,tmp[ct++]=p[j++];
else sum+=giv(i),tmp[ct++]=p[i++];
}
rep(i,l,r)p[i]=tmp[i];
}
注意一定要归并排序,不然左右两边就不一定有单调性。
即:当i越界或j不越界但不合法,更新j的答案并把j后移。否则,计算i的贡献并后移。

浙公网安备 33010602011771号