1. 程式人生 > >CodeForces - 1075C The Tower is Going Home 【思維+STL二分查詢】

CodeForces - 1075C The Tower is Going Home 【思維+STL二分查詢】

題目傳送門

題目描述:在寬109高109的棋盤上,從下到上編號為1到10^9,從左到右編號為1到10^9。因此,對於棋盤的每個單元格,可以指定座標(x,y),其中x是列號,y是行號。在棋盤的左下角(1,1)處有一個棋子,在棋盤上有很多的阻隔牆(垂直的和水平的),求棋子到達最後一行至少需要翻過幾道牆。

輸入:第一行包含兩個整數n和m(0≤n,m≤10^5)垂直和水平阻隔牆的數量。

以下n行包含一個整數x(1≤x < 109),表示在x和x+1列之間有一道垂直阻隔牆。

以下m行包含三個整數x1,x2和y(1 ≤x1,x2≤10^9,1≤y < 10^9),表示在第y行與第y+1行之間有一道從第x1列到第x2列的水平阻隔牆。

輸出:棋子到達最後一行至少需要翻過幾道牆。

解題思路:實際上這道題是要求有多少個封閉的空間,且任意兩個封閉空間的都不能共用一條邊。如果水平阻隔牆的起始位置不是第一列,那麼一定不會組成封閉空間,如果水平阻隔牆的長度等於10^9,那麼棋子至少要翻過這道牆,因為任意兩道牆都不能有公共邊,所以用vis陣列標記已經組成了封閉空間的垂直阻隔牆。

AC程式碼:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
using namespace std;
#define io ios::sync_with_stdio(0),cin.tie(0)
#define ms(arr) memset(arr,0,sizeof(arr))
#define inf 0x3f3f3f
typedef long long ll;
const int mod=1e9+7;
const int maxn=2e5+7;
int n,m;
int b[maxn];
int vis[maxn];
int main()
{
    io;
    cin>>n>>m;
    for(int i=0; i<n; i++)
        cin>>b[i];
    sort(b,b+n);
    ms(vis);
    int ans=0;
    for(int i=1; i<=m; i++)
    {
        int a1,a2,c;
        cin>>a1>>a2>>c;
        if(a1==1)//水平阻隔牆的起始位置必須是第一列,才有可能組成封閉空間
        {
            if(a2==1000000000)//水平阻隔牆的長度等於10^9,那麼棋子至少要翻過這道牆
            {
                ans++;
                continue;
            }
            int k=upper_bound(b,b+n,a2)-b-1;//找到第一個不大於水平阻隔牆長度的垂直阻隔牆,並與之組成封閉空間
            while(vis[k]==1&&k>=0)//若這道垂直阻隔牆已經與其他水平阻隔牆組成了封閉空間,那麼向下尋找,直到找到未被標記的垂直阻隔牆
            {
                k--;
            }
            if(k>=0)//如果能夠找到這道垂直阻隔牆,那麼能夠組成封閉空間,需要翻牆
            {
                ans++;
                vis[k]=1;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}