猴戏世家 解题报告

Problem A: 猴戏世家

1394419-20190118190001808-454440471.png

1394419-20190118190020320-267127329.png

1394419-20190118190025567-311301199.png


考试时拿染色企图水20分结果hash冲突了,rp++

考虑离线乱搞一下,可以先把每个点最开始被哪个矩形包着求出来,然后把矩形被哪个矩形包着求出来。

这样点作为对矩形的贡献成为矩形的权,矩形连边后形成一把森林。

按y从大到小进行扫描线,拿set维护这个扫描线,每次加入矩形时把自己左边比自己晚的扔掉,然后随便维护一下连边和权值。

然后考虑到每个矩形可以对完全包含它的矩形做贡献,于是我们倒序删除矩形,维护一个带权并查集,每次把贡献扔给父亲就可以了


Code:

#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
const int N=6e5+10;
int n,m,mx[N],my[N],qx[N],qy[N],d[N],cnt;
struct beecute
{
    int p,id;
    beecute(){}
    beecute(int p,int id){this->p=p,this->id=id;}
    bool friend operator <(beecute a,beecute b){return a.p==b.p?a.id<b.id:a.p<b.p;}
};
std::vector<beecute> bee[N];
std::set <beecute> s;
std::set <beecute>::iterator it;
int par[N],f[N],val[N],ans[N];
int Find(int x){return f[x]=f[x]==x?x:Find(f[x]);}
void Merge(int x,int y)
{
    f[x]=Find(y);
    val[f[x]]+=val[x];
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",mx+i,my+i),d[++cnt]=my[i];
    scanf("%d",&m);
    for(int i=1;i<=m;i++) scanf("%d%d",qx+i,qy+i),d[++cnt]=qy[i],f[i]=i;
    std::sort(d+1,d+1+cnt);
    cnt=std::unique(d+1,d+1+cnt)-d-1;
    for(int i=1;i<=n;i++)
    {
        my[i]=std::lower_bound(d+1,d+1+cnt,my[i])-d;
        bee[my[i]].push_back(beecute(mx[i],0));
    }
    for(int i=1;i<=m;i++)
    {
        qy[i]=std::lower_bound(d+1,d+1+cnt,qy[i])-d;
        bee[qy[i]].push_back(beecute(qx[i],i));
    }
    for(int i=cnt;i;i--)
    {
        std::sort(bee[i].begin(),bee[i].end());
        for(int j=bee[i].size()-1;~j;j--)
        {
            int id=bee[i][j].id;
            it=s.lower_bound(bee[i][j]);
            if(id)
            {
                if(it!=s.end())
                    par[id]=it->id;
                if(it==s.begin()) {s.insert(bee[i][j]);continue;}
                --it;
                while(it!=s.begin()&&it->id>id)
                    s.erase(it--);
                if(!s.empty()&&it==s.begin()&&it->id>id)
                    s.erase(it);
                s.insert(bee[i][j]);
            }
            else if(it!=s.end())
                ++val[it->id];
        }
    }
    for(int i=m;i;i--)
    {
        ans[i]=val[i];
        Merge(i,par[i]);
    }
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

2019.1.18

转载于:https://www.cnblogs.com/butterflydew/p/10289307.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值