【CFGym102586L】Yosupo's Algorithm(分治+二维数点)
题目链接
- 给定二维平面上 \(n\) 个红点和 \(n\) 个蓝点,每个点有一个点权。
- \(q\) 次询问,每次给定 \(L,R\)。要求找到一个红点 \((rx,ry)\)(权值 \(rv\)) 和一个蓝点 \((bx,by)\)(权值 \(bv\)),满足:\(ry < by\);\(rx < L,bx > R\) 或 \(rx > L,bx < R\)。求 \(rv+bv\) 的最大值。
- \(1\le n\le10^5\),\(1\le q\le5\times10^5\),所有 \(x,L,R\) 各不相同,所有 \(y\) 各不相同
分治预处理
考虑 \(ry < by\) 这一限制,我们先将所有点按照 \(y\) 排序,然后分治,每次考虑红点在左区间、蓝点在右区间时的贡献。
发现 \(rx < L,bx > R\) 或 \(rx > L,bx < R\) 等价于 \([rx < L]=[bx > R]\)。对于红点,记它的类型为 \([rx < L]\);对于蓝点,记它的类型为 \([bx > R]\)。
于是可以用反证法证明,选中的红点和蓝点至少有一个是所在区间内权值最大的:如果选中的两个点都不是权值最大的,则选中的红点类型与权值最大的蓝点类型必然不同——否则就可以把选中的蓝点替换成权值最大的蓝点,同理选中的蓝点类型与权值最大的红点类型必然相同。但这样一来,由于选中的红点和蓝点类型相同,那么权值最大的红点和蓝点类型也就相同,选择它们肯定更优,产生矛盾。
因此只要将左区间最大红点与右区间所有蓝点视作一组可能的匹配关系,右区间最大蓝点与左区间所有红点视作一组可能的匹配关系即可。
二维数点求解答案
一组匹配关系可以表示为 \((rx,bx,v)\)。
询问就是对于所有满足 \(rx < L,bx > R\) 的匹配关系和 \(rx > L,bx < R\) 的匹配关系询问 \(v\) 的最大值,也就是两个二维数点问题。
代码:\(O(n\log^2 n+q\log n)\)
#include
#define Tp template
#define Ts template
#define Rg register
#define RI Rg int
#define Cn const
#define CI Cn int&
#define I inline
#define W while
#define N 100000
#define M 500000
#define SZ N*40
using namespace std;
namespace FastIO
{
#define FS 100000
#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
int ff,OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
Tp I void read(Ty& x) {x=0,ff=1;W(!isdigit(oc=tc())) ff=oc^'-'?1:-1;W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));x*=ff;}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void writeln(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc('\n');}
I void NA() {pc('-'),pc('1'),pc('\n');}
}using namespace FastIO;
int n;struct P {int x,y,w;I bool operator < (Cn P& o) Cn {return y>1;
for(x=-1,i=l;i<=mid;++i) p[i].x<0&&(!~x||p[x].w0&&(Add(x,i),0);//左区间最大红点与右区间所有蓝点
for(x=-1,i=mid+1;i<=r;++i) p[i].x>0&&(!~x||p[x].w
q[i].x) T2.U(s[j].y,s[j].w),--j;//第二种二维数点
for(i=1;i<=Qt;++i) ans[i]?writeln(ans[i]):NA();return clear(),0;
}