• 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]);
    }
    
  • 相关阅读:
    刚好遇见你——软件工程
    int main(int argc,char* argv[]) 简单理解
    奇偶数分离
    A+B Problem
    日期计算
    正三角形的外接圆面积
    数数小木块
    谁是最好的Coder
    水仙花数
    5个数求最值
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12800529.html
Copyright © 2020-2023  润新知