1. 程式人生 > >BZOJ3718[PA2014]Parking——樹狀數組

BZOJ3718[PA2014]Parking——樹狀數組

can space scan amp src stack 數量 https -i

題目描述

你的老板命令你將停車場裏的車移動成他想要的樣子。
停車場是一個長條矩形,寬度為w。我們以其左下角頂點為原點,坐標軸平行於矩形的邊,建立直角坐標系。停車場很長,我們可以認為它一直向右邊伸展到無窮遠處。
車都是邊平行於坐標軸的矩形,大小可能不同。你可以將車任意地平移(但不能旋轉),只要他們不超出停車場的邊界,且不能互相碰撞,但緊挨著是允許的(即任意時刻任兩輛車的重疊面積為0)。
你知道目前各輛車的擺放位置,以及老板心中所想的位置。你需要判斷是否可以辦到老板的任務。

技術分享圖片

輸入

第一行為一個整數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行,格式和意義同上,表示車的目標位置。

輸出

輸出t行,第i行為TAK(是)或NIE(否),表示第i組測試數據中能否按照要求進行移動。

樣例輸入

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

樣例輸出

TAK
NIE
發現如果一個車能停到目標位置那麽只要這兩個位置之間每輛車的寬度與這個車的寬度之和不大於w就行。 對於兩輛車x,y如果他們當前的相對位置與目標相對位置不同(即當前是x,y,目標是y,x)那麽這兩個車的寬度之和就要<=w。 用樹狀數組維護寬度的前綴最大值每次查詢前綴最大值和當前車寬度加和是否<=w即可。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct miku
{
    int a,b,c,d;
    int w;
    int id;
}s1[50010],s2[50010];
int v[50010];
int n,m,T;
int flag;
int pos[50010];
bool cmp(miku a,miku b)
{
    if(a.a!=b.a)
    {
        return a.a<b.a;
    }
    return a.c<b.c;
}
void add(int x,int val)
{
    for(int i=x;i<=n;i+=i&-i)
    {
        v[i]=max(v[i],val);
    }
}
int ask(int x)
{
    int res=0;
    for(int i=x;i;i-=i&-i)
    {
        res=max(res,v[i]);
    }
    return res;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        flag=0;
        memset(v,0,sizeof(v));
        memset(pos,0,sizeof(pos));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&s1[i].a,&s1[i].b,&s1[i].c,&s1[i].d);
            if(s1[i].a>s1[i].c)
            {
                swap(s1[i].a,s1[i].c);
            }
            if(s1[i].b>s1[i].d)
            {
                swap(s1[i].b,s1[i].d);
            }
            s1[i].w=s1[i].d-s1[i].b;
            s1[i].id=i;
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&s2[i].a,&s2[i].b,&s2[i].c,&s2[i].d);
            if(s2[i].a>s2[i].c)
            {
                swap(s2[i].a,s2[i].c);
            }
            if(s2[i].b>s2[i].d)
            {
                swap(s2[i].b,s2[i].d);
            }
            s2[i].w=s2[i].d-s2[i].b;
            s2[i].id=i;
        }
        sort(s1+1,s1+1+n,cmp);
        sort(s2+1,s2+1+n,cmp);
        for(int i=1;i<=n;i++)
        {
            pos[s1[i].id]=i;
        }
        for(int i=n;i>=1;i--)
        {
            if(flag==1)
            {
                break;
            }
            if(ask(pos[s2[i].id])+s2[i].w>m)
            {
                flag=1;
            }
            add(pos[s2[i].id],s2[i].w);
        }
        printf(flag==1?"NIE\n":"TAK\n");
    }
     
}

BZOJ3718[PA2014]Parking——樹狀數組