CodeForces - 1075C The Tower is Going Home 【思維+STL二分查詢】
阿新 • • 發佈:2018-11-19
題目描述:在寬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; }