• 【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<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #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<o.y;}}p[2*N+5];
    int ct,dc,dv[SZ+5],Qt,ans[M+5];struct S {int x,y,w;I bool operator < (Cn S& o) Cn {return x<o.x;}}q[M+5],s[SZ+5];
    struct TreeArray1
    {
    	int a[N+5];I void U(RI x,CI v) {W(x&&a[x]<v) a[x]=v,x-=x&-x;}I int Q(RI x) {RI t=0;W(x<=dc) t=max(t,a[x]),x+=x&-x;return t;}
    }T1;
    struct TreeArray2
    {
    	int a[N+5];I void U(RI x,CI v) {W(x<=dc&&a[x]<v) a[x]=v,x+=x&-x;}I int Q(RI x) {RI t=0;W(x) t=max(t,a[x]),x-=x&-x;return t;}
    }T2;
    I void Solve(CI l,CI r)//分治预处理
    {
    	#define Add(i,j) (s[++ct]=(S){p[i].x,p[j].x,p[i].w+p[j].w})
    	if(l==r) return;RI i,x,mid=l+r>>1;
    	for(x=-1,i=l;i<=mid;++i) p[i].x<0&&(!~x||p[x].w<p[i].w)&&(x=i);if(~x) for(i=mid+1;i<=r;++i) p[i].x>0&&(Add(x,i),0);//左区间最大红点与右区间所有蓝点
    	for(x=-1,i=mid+1;i<=r;++i) p[i].x>0&&(!~x||p[x].w<p[i].w)&&(x=i);if(~x) for(i=l;i<=mid;++i) p[i].x<0&&(Add(i,x),0);//右区间最大蓝点与左区间所有红点
    	Solve(l,mid),Solve(mid+1,r);
    }
    int main()
    {
    	RI i;for(read(n),i=1;i<=n;++i) read(p[i].x,p[i].y,p[i].w);for(i=1;i<=n;++i) read(p[n+i].x,p[n+i].y,p[n+i].w);
    	#define GV(x) (lower_bound(dv+1,dv+dc+1,x)-dv)
    	for(sort(p+1,p+2*n+1),Solve(1,n<<1),sort(s+1,s+ct+1),i=1;i<=ct;++i) dv[i]=s[i].y;//按点按y排序然后分治;将关系按第一维排序
    	for(sort(dv+1,dv+ct+1),dc=unique(dv+1,dv+ct+1)-dv-1,i=1;i<=ct;++i) s[i].y=GV(s[i].y);//离散化
    	for(read(Qt),i=1;i<=Qt;++i) read(q[i].x,q[i].y),q[i].w=i;sort(q+1,q+Qt+1);//按询问按第一维排序
    	RI j;for(i=j=1;i<=Qt;ans[q[i].w]=T1.Q(GV(q[i].y+1)),++i) W(j<=ct&&s[j].x<q[i].x) T1.U(s[j].y,s[j].w),++j;//第一种二维数点
    	for(i=Qt,j=ct;i;ans[q[i].w]=max(ans[q[i].w],T2.Q(GV(q[i].y)-1)),--i) W(j&&s[j].x>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;
    }
    
  • 相关阅读:
    海量文档查同或聚类问题 Locality Sensitive Hash 算法
    Python之道 (大道至简)
    Inside C++ object Model构造函数
    Python标准模块logging
    Inside C++ object Model多态(ObjectOriented)
    应用Notepad++的正则表达式完成较复杂替换的一个小例子
    维护FAST可用的一些命令 持续更新
    SharePoint List的List Template ID明细表
    SharePoint 2010 Incoming Email怎么配?
    使用ContentDeploymentJob.AddQuickDeployObject的时候, 请注意第三个参数一定要使用Server Relative URL
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CFGym102586L.html
Copyright © 2020-2023  润新知