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

版权声明:本文为博主原创文章,转载请注明出处( • ̀ω•́ )✧ https://blog.csdn.net/wangws_sb/article/details/83960916

题目传送门

题目描述:在宽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;
}

猜你喜欢

转载自blog.csdn.net/wangws_sb/article/details/83960916