Rectangles CodeForces - 1028C

http://codeforces.com/contest/1028/problem/C

问是否有一个点被至少(n-1)个矩形覆盖过

利用扫描线思想 将矩形的左右边用来更新线段树 线段树维护区间最值和最值的下标 当更新了(n-1)条边和n条边时分别判断一下 当前是否存在一个点被覆盖了至少(n-1)次 有则输出

 

其实直接搞一个前缀后缀就好 枚举到i时 看i-1之前和i+1之后里最大的x1是否小于等于x2 最大的y1是否小于等于y2 是则说明除去当前矩形后 剩余n-1个矩形都相交于某一区域

智障啊 以前还写过矩形相交的题 智商不够 数据结构来凑。。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

struct node1
{
    int tp;
    int y1;
    int y2;
    int x;
};

struct node2
{
    int l;
    int r;
    int val;
    int laz;
    int id;
};

node1 seg[300010];
node2 tree[1200010];
int tmpx[300010],tmpy[300010],flag1[600010],flag2[600010];
int n,lenx,leny,res;

bool cmp(node1 n1,node1 n2)
{
    if(n1.x==n2.x) return n1.tp<n2.tp;
    else return n1.x<n2.x;
}

void pushup(int cur)
{
    if(tree[2*cur].val>tree[2*cur+1].val)
    {
        tree[cur].val=tree[2*cur].val;
        tree[cur].id=tree[2*cur].id;
    }
    else
    {
        tree[cur].val=tree[2*cur+1].val;
        tree[cur].id=tree[2*cur+1].id;
    }
}

void pushdown(int cur)
{
    if(tree[cur].laz!=0)
    {
        tree[2*cur].val+=tree[cur].laz;
        tree[2*cur].laz+=tree[cur].laz;
        tree[2*cur+1].val+=tree[cur].laz;
        tree[2*cur+1].laz+=tree[cur].laz;
        tree[cur].laz=0;
    }
}

void build(int l,int r,int cur)
{
    int m;
    tree[cur].l=l;
    tree[cur].r=r;
    tree[cur].val=0;
    tree[cur].laz=0;
    if(l==r)
    {
        tree[cur].id=l;
        return;
    }
    m=(l+r)/2;
    build(l,m,2*cur);
    build(m+1,r,2*cur+1);
    pushup(cur);
}

void update(int pl,int pr,int val,int cur)
{
    if(pl<=tree[cur].l&&tree[cur].r<=pr)
    {
        tree[cur].val+=val;
        tree[cur].laz+=val;
        return;
    }
    pushdown(cur);
    if(pl<=tree[2*cur].r) update(pl,pr,val,2*cur);
    if(pr>=tree[2*cur+1].l) update(pl,pr,val,2*cur+1);
    pushup(cur);
}

int main()
{
    int i,x1,y1,x2,y2,cnt;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        tmpx[++lenx]=x1,tmpx[++lenx]=x2;
        tmpy[++leny]=y1,tmpy[++leny]=y2;
        seg[2*i-1].tp=1,seg[2*i-1].y1=y1,seg[2*i-1].y2=y2,seg[2*i-1].x=x1;
        seg[2*i].tp=2,seg[2*i].y1=y1,seg[2*i].y2=y2,seg[2*i].x=x2;
    }
    sort(tmpx+1,tmpx+lenx+1);
    sort(tmpy+1,tmpy+leny+1);
    lenx=unique(tmpx+1,tmpx+lenx+1)-tmpx-1;
    leny=unique(tmpy+1,tmpy+leny+1)-tmpy-1;
    for(i=1;i<=2*n;i++)
    {
        seg[i].y1=lower_bound(tmpy+1,tmpy+leny+1,seg[i].y1)-tmpy;
        seg[i].y2=lower_bound(tmpy+1,tmpy+leny+1,seg[i].y2)-tmpy;
        seg[i].x=lower_bound(tmpx+1,tmpx+lenx+1,seg[i].x)-tmpx;
    }
    sort(seg+1,seg+2*n+1,cmp);
    build(1,leny,1);
    cnt=0;
    for(i=1;i<=2*n;i++)
    {
        if(seg[i].tp==1)
        {
            update(seg[i].y1,seg[i].y2,1,1);
            cnt++;
        }
        else
        {
            update(seg[i].y1,seg[i].y2,-1,1);
        }
        if(cnt==n-1)
        {
            if(tree[1].val>=n-1)
            {
                printf("%d %d\n",tmpx[seg[i].x],tmpy[tree[1].id]);
                break;
            }
        }
        else if(cnt==n)
        {
            printf("%d %d\n",tmpx[seg[i].x],tmpy[tree[1].id]);
            break;
        }
    }

    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值