http://www.51nod.com/Challenge/Problem.html#problemId=1559

 

倘若矩形是受保护的,那么矩形内每一行至少有一个车或者每一列至少有一个车

 

判断矩形内每一列都有一个车:

线段树中维护x坐标这一列车的最大y坐标

那么扫描线扫过矩形的上边界时

如果矩形左右边界内,车的最大y坐标中最小的那个大于等于矩形的下边界

那么这个矩形的每一列都有一个车

将车按y坐标从小到大排序,每次扫到一条矩形的上边界,

将y坐标<=这一上边界的车都加入线段树,即用车的y坐标更新线段树

即可实现这一过程

 

判断矩形每一行都有一个车同理

 

 

#include<cstdio>
#include<iostream> 
#include<algorithm>

using namespace std;

#define N 100002

struct car
{
    int x,y;
}g[N<<1];

struct line
{
    int li,ri,ui,di,id;
    bool ok;
}e[N<<1];

int mi[N<<2],tmp;

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}

bool cmp1(car p,car q)
{
    return p.y<q.y;
}

bool cmp2(line p,line q)
{
    return p.ui<q.ui;
}    

bool cmp3(car p,car q)
{
    return p.x<q.x;
}

bool cmp4(line p,line q)
{
    return p.ri<q.ri;
}

bool cmp5(line p,line q)
{
    return p.id<q.id;
}

void build(int k,int l,int r)
{
    mi[k]=0;
    if(l==r) return;
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
}

void change(int k,int l,int r,int pos,int w)
{
    if(l==r)
    {
        mi[k]=w;
        return;
    }
    int mid=l+r>>1;
    if(pos<=mid) change(k<<1,l,mid,pos,w);
    else change(k<<1|1,mid+1,r,pos,w);
    mi[k]=min(mi[k<<1],mi[k<<1|1]);
}

void query(int k,int l,int r,int opl,int opr)
{
    if(l>=opl && r<=opr)
    {
        tmp=min(tmp,mi[k]);
        return;
    }
    int mid=l+r>>1;
    if(opl<=mid) query(k<<1,l,mid,opl,opr);
    if(opr>mid) query(k<<1|1,mid+1,r,opl,opr);
}

int main()
{
    int n,m,k,q;
    read(n); read(m); read(k); read(q);
    for(int i=1;i<=k;++i) 
    {
        read(g[i].x);
        read(g[i].y);
    }
    int X1,X2,Y1,Y2;
    for(int i=1;i<=q;++i) 
    {
        read(X1); read(Y1); read(X2); read(Y2);
        e[i].li=X1;
        e[i].ri=X2;
        e[i].ui=Y2;
        e[i].di=Y1;
        e[i].id=i;
    }
    int now=1;
    sort(g+1,g+k+1,cmp1);
    sort(e+1,e+q+1,cmp2);
    for(int i=1;i<=q;++i)
    {
        while(now<=k && g[now].y<=e[i].ui) 
        {
            change(1,1,n,g[now].x,g[now].y);
            now++;
        }
        tmp=1e6;
        query(1,1,n,e[i].li,e[i].ri);
        if(tmp>=e[i].di) e[i].ok=true;
    }
    now=1;
    sort(g+1,g+k+1,cmp3);
    sort(e+1,e+q+1,cmp4);
    build(1,1,m);
    for(int i=1;i<=q;++i)
    {
        while(now<=k && g[now].x<=e[i].ri) 
        {
            change(1,1,m,g[now].y,g[now].x);
            now++;
        }
        if(e[i].ok) continue;
        tmp=1e6;
        query(1,1,m,e[i].di,e[i].ui);
        if(tmp>=e[i].li) e[i].ok=true;
    }
    sort(e+1,e+q+1,cmp5);
    for(int i=1;i<=q;++i) puts(e[i].ok ? "YES" : "NO");
}

 

 

 

 

1559 车和矩形
  1. 1.5 秒
  2. 131,072.0 KB
  3. 160 分
  4. 6级题
 

波雷卡普有一个n×m,大小的棋盘,上面有k个车。他又放了q个矩形在上面。每一个矩形要受到保护。矩形受到保护的意思是对于该矩形内部所有的格子能够被这个矩形内的某个车攻击到或者被占据,和矩形外面的车无关,即矩形外面的车不能攻击到矩形里面。车的位置是固定的。

样例解释:

51nod 1559 车和矩形_线段树

对于最后一个矩形,用红色框框表示的,因为(1,2)不能被某个车攻击到,所以是NO。

收起
 
输入
单组测试数据。
第一行有4个整数 n, m, k 和q (1≤n,m≤100000, 1≤k,q≤200000),表示棋盘大小,棋盘上车的数目,放置矩形的数目。
棋盘的列是从左到右按照1到n编号,行是从下到上按照1到m编号。
接下来k行每一行有两个整数x y(1≤x≤n,1≤y≤m),表示车的位置。输入保证所有车的位置是不一样的。
接下来q行每一行有四个整数x1 y1 x2 y2(1≤x1≤x2≤n, 1≤y1≤y2≤m)。
表示符合x1≤x≤x2, y1≤y≤y2的格子在该矩形内。
输出
对于每一个矩形,如果他是受保护的输出YES,否则输出NO。
输入样例
样例输入1
4 3 3 3
1 1
3 2
2 3
2 3 2 3
2 1 3 3
1 2 2 3
输出样例
样例输出1
YES
YES
NO

 

 

 

 
作者:xxy
本文版权归作者所有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。