Gym102586L Yosupo's Algorithm

Link
先对(y)分治分治,考虑(yin[l,mid])的红点和(yin(mid,r])的蓝点的贡献。
一个很显然结论是:可能出现在答案中的点对中,至少有一个点是在该(y)坐标范围内该颜色点中权值最大的点。
那么这样我们就可以求出(O(nlog n))对可能对答案有影响的点对。
然后对两种情况分别扫描线+BIT维护即可。

#include<cctype>
#include<cstdio>
#include<vector>
#include<cstring>
#include<utility>
#include<algorithm>
using pi=std::pair<int,int>;
char ibuf[1<<25|1],*iS=ibuf;int read(){int x=0,f=1;while(isspace(*iS))++iS;if(*iS=='-')f=-1,++iS;while(isdigit(*iS))(x*=10)+=*iS++&15;return f*x;}
const int N=200007,M=1200007,inf=1e9;
int n,q,cx,cp,tx[M],ans[M],bit[M];pi qry[M],pr[20*N];std::vector<int>vec[M];
struct node{int x,y,w,col;}a[N];
int operator<(const node&a,const node&b){return a.y<b.y;}
void add(int p,int v){for(;p<=cx;p+=p&-p)bit[p]=std::max(bit[p],v);}
int ask(int p){int r=-inf;for(;p;p^=p&-p)r=std::max(r,bit[p]);return r;}
void solve(int l,int r)
{
    if(l==r) return;
    int mid=(l+r)/2,pos;solve(l,mid),solve(mid+1,r);
    pos=0;for(int i=l;i<=mid;++i) if(!a[i].col&&a[i].w>a[pos].w) pos=i;
    if(pos) for(int i=mid+1;i<=r;++i) if(a[i].col) pr[++cp]={pos,i};
    pos=0;for(int i=mid+1;i<=r;++i) if(a[i].col&&a[i].w>a[pos].w) pos=i;
    if(pos) for(int i=l;i<=mid;++i) if(!a[i].col) pr[++cp]={i,pos};
}
int main()
{
    fread(ibuf,1,1<<25,stdin),n=read();
    for(int i=1;i<=n;++i) a[i]={tx[++cx]=read(),read(),read(),0};
    for(int i=1;i<=n;++i) a[i+n]={tx[++cx]=read(),read(),read(),1};
    std::sort(a+1,a+n+n+1,[](const node&a,const node&b){return a.y<b.y;}),solve(1,n+n),q=read(),memset(ans+1,-1,4*q);
    for(int i=1;i<=q;++i) qry[i]={read(),read()},tx[++cx]=qry[i].first,tx[++cx]=qry[i].second;
    std::sort(tx+1,tx+cx+1),cx=std::unique(tx+1,tx+cx+1)-tx-1;
    for(int i=1;i<=n+n;++i) a[i].x=std::lower_bound(tx+1,tx+cx+1,a[i].x)-tx;
    for(int i=1;i<=q;++i) qry[i]={std::lower_bound(tx+1,tx+cx+1,qry[i].first)-tx,std::lower_bound(tx+1,tx+cx+1,qry[i].second)-tx},vec[qry[i].first].push_back(i);
    std::sort(pr+1,pr+cp+1,[](const pi&i,const pi&j){return a[i.first].x<a[j.first].x;}),memset(bit+1,-0x3f,4*cx);
    for(int i=1,j=1;i<=cx;++i)
    {
	for(;j<=cp&&a[pr[j].first].x<=i;++j) add(cx-a[pr[j].second].x+1,a[pr[j].first].w+a[pr[j].second].w);
	for(int id:vec[i]) ans[id]=std::max(ans[id],ask(cx-qry[id].second+1));
    }
    std::reverse(pr+1,pr+cp+1),memset(bit+1,-0x3f,4*cx);
    for(int i=cx,j=1;i;--i)
    {
	for(;j<=cp&&a[pr[j].first].x>=i;++j) add(a[pr[j].second].x,a[pr[j].first].w+a[pr[j].second].w);
	for(int id:vec[i]) ans[id]=std::max(ans[id],ask(qry[id].second));
    }
    for(int i=1;i<=q;++i) printf("%d
",ans[i]);
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12800529.html