bzoj3718: [PA2014]Parking

Description

你的老板命令你将停车场里的车移动成他想要的样子。
停车场是一个长条矩形,宽度为w。我们以其左下角顶点为原点,坐标轴平行于矩形的边,建立直角坐标系。停车场很长,我们可以认为它一直向右边伸展到无穷远处。
车都是边平行于坐标轴的矩形,大小可能不同。你可以将车任意地平移(但不能旋转),只要他们不超出停车场的边界,且不能互相碰撞,但紧挨着是允许的(即任意时刻任两辆车的重叠面积为0)。
你知道目前各辆车的摆放位置,以及老板心中所想的位置。你需要判断是否可以办到老板的任务。

Input

第一行为一个整数t(1<=t<=20),表示测试数据数量。
对于每组测试数据,第一行两个整数n,w(1<=n<=50000,1<=w<=10^9),分别表示车的数量和停车场的宽度。
接下来n行,第i行有四个整数x1,y1,x2,y2(0<=x1,x2<=10^9,0<=y1,y2<=w),表示编号为i的车的当前位置是由x1,y1,x2,y2确定的矩形。(注意:数据有可能出现x1>x2或y1>y2)
再接下来n行,格式和意义同上,表示车的目标位置。

Output

输出t行,第i行为TAK(是)或NIE(否),表示第i组测试数据中能否按照要求进行移动。

Sample Input

2

3 3

0 0 2 2

2 1 4 3

4 0 6 1

0 0 2 2

2 1 4 3

0 2 2 3

3 3

0 0 2 2

2 1 4 3

4 0 6 1

2 1 4 3

0 0 2 2

4 0 6 1
Sample Output

TAK

NIE

我们考虑到,不合法的情况肯定是两辆车目标要交换位置,但他们并不可以交换。。
于是就可以做了

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int N=50005;
struct qq
{
    int x1,y1,x2,y2;
    int z,id;
    bool operator <(const qq& a)const
    {
        return x1==a.x1?x2<a.x2:x1<a.x1;
    };
}s[N],s1[N];int n,w;
int pos[N];
int f[N];
int mymax (int x,int y){return x>y?x:y;}
int lb (int x){return x&(-x);}
int get (int x)
{
    int tt=0;
    while (x>=1)
    {
        tt=mymax(tt,f[x]);
        x-=lb(x);
    }
    return tt;
}
void add (int x,int y)
{
    while (x<=n)
    {
        f[x]=mymax(f[x],y);
        x+=lb(x);
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        memset(f,0,sizeof(f));
        scanf("%d%d",&n,&w);
        for (int u=1;u<=n;u++)
        {
            scanf("%d%d%d%d",&s[u].x1,&s[u].y1,&s[u].x2,&s[u].y2);
            if (s[u].x1>s[u].x2) swap(s[u].x1,s[u].x2);
            if (s[u].y1>s[u].y2) swap(s[u].y1,s[u].y2);
            s[u].z=s[u].y2-s[u].y1;s[u].id=u;
        }
        for (int u=1;u<=n;u++)
        {
            scanf("%d%d%d%d",&s1[u].x1,&s1[u].y1,&s1[u].x2,&s1[u].y2);
            if (s1[u].x1>s1[u].x2) swap(s1[u].x1,s1[u].x2);
            if (s1[u].y1>s1[u].y2) swap(s1[u].y1,s1[u].y2);
            s1[u].z=s1[u].y2-s1[u].y1;s1[u].id=u;
        }
        sort(s+1,s+1+n);sort(s1+1,s1+1+n);
        for (int u=1;u<=n;u++) pos[s[u].id]=u;
        bool tf=true;
        for (int u=n;u>=1;u--)
        {
            if (get(pos[s1[u].id])+s1[u].z>w) {tf=false;break;}
            add(pos[s1[u].id],s1[u].z);
        }
        if (tf) printf("TAK\n");
        else printf("NIE\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值