zoukankan      html  css  js  c++  java
  • Lyft Level 5 Challenge 2018

    https://codeforces.com/contest/1075/problem/C

    题意

    一个宽为1e9*1e9的矩阵中的左下角,放置一个车(车可以移动到同一行或同一列),放置一些墙,竖的占据一列,横的有一的长度,问车从最下角走到第1e9行最少拆多少面墙?

    思路

    • 看了看数据范围以为是一道离散化的题,但是发现车可以往左走
    • 然后再明确了一下题意,墙是永久拆去的,反应到可以优先拆竖着的墙,然后假如剩下横着的墙比竖着的墙少的话,可以直接拆横着的墙
    • 写之前看了一下题意,说横着的墙不会有交点,然后大致确立了贪心策略:

    将横着的墙按高度排序,然后一层一层向上爬,更新最右点,假如最右点>p[i].x2,然后就可以向上爬,假如最右点<=p[i].x2,看剩下横着的边多还是竖着的边多,决定是否要更新最右点

    • 但是上述思路是错的,因为剩下的横边其实有的不一定要拆

    题解

    • 首先需要明确两个题意,这对解这道题非常重要
      • 横着的边不会有交点,这一点非常重要,因为根据车的性质,假如横着的边有空隙,假设没有竖边,他就一定可以向上走,所以只需要判每条边的左端点是否1,1的边才需要记录,因为车上不去,这样所有的横边就变成了从1开始的边
      • 墙是永久拆除的,这样竖着的边就等于一个上界,上界越大,意味着要拆的竖边越多,意味着能通过的横边越多
      • 然后就可以枚举竖边(上界),然后找到横边大于上界的点,更新答案(这就是双指针)
    #include<bits/stdc++.h>
    #define pb push_back
    #define M 1e9
    using namespace std;
    int n,m,i,ans,j,Y,x1,x2;
    vector<int>y,x;
    
    int main(){
        cin>>n>>m;
        for(i=0;i<n;i++){scanf("%d",&Y);y.pb(Y);}
        y.pb(M);
        for(i=0;i<m;i++){
            scanf("%d%d%d",&x1,&x2,&Y);
            if(x1==1)x.pb(x2);
        }
        sort(x.begin(),x.end());
        sort(y.begin(),y.end());
        ans=M;
        for(i=0,j=0;i<=n;i++){
            while(j<x.size()&&x[j]<y[i])j++;
            ans=min(ans,(int)(i+x.size()-j));
        }
        cout<<ans;
    }
    
  • 相关阅读:
    codevs 3160 最长公共子串
    bzoj1593 [Usaco2008 Feb]Hotel 旅馆
    bzoj1230 [Usaco2008 Nov]lites 开关灯
    洛谷P1558 色板游戏
    洛谷P2253 好一个一中腰鼓!
    洛谷P2345 奶牛集会
    TopCoder SRM420 Div1 500pt RedIsGood
    洛谷P3144 [USACO16OPEN]关闭农场Closing the Farm_Silver
    洛谷P1455 搭配购买
    洛谷P2398 GCD SUM
  • 原文地址:https://www.cnblogs.com/VIrtu0s0/p/9948991.html
Copyright © 2011-2022 走看看