zoukankan      html  css  js  c++  java
  • hdu 6992 / 2021“MINIEYE杯”中国大学生算法设计超级联赛(4)1008 Lawn of the Dead

    https://acm.hdu.edu.cn/showproblem.php?pid=6992

    题意:

    n*m网格图上有k个障碍,初始位置(1,1),只能向下和向右走

    问图上有多少个点是可以被走到的

    数据范围1e5

    n*m很大,但是障碍物比较少

    考虑被2个障碍物夹住的区间[L,R],确定出这个区间最靠左的可以被走到的位置x,那么这个区间的贡献是R-x+1

    x怎么确定?

    因为之这是一段被2个障碍物夹住的区间,所以x不可能是从左边走过去的,那就只能是从上边走过去的

    所以如果我们能够统计出上一行可以被走到的所有区间,从中找出与[L,R]有交集的区间[l,r],那[L,R]这段区间的贡献就是 R-max(L,l)+1

    思路就是这样,关键是如何高效的实现

    一是如何找出所有被障碍物夹住的区间

    二是如何找相邻两行区间的交集

    先把所有的障碍物以行位第一关键字,列位第二关键字排序

    按行求解,先求本行的被障碍物夹住的区间,再求这些区间与上一行可行区间的交集

    求本行的被障碍物夹住的区间就扫一遍本行的障碍物就行

    求区间交集也类似,用2个位置指针,1个指向上一行可行区间用到哪一个,一个指向本行被障碍物夹住的区间用到哪一个

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define N 100005
    
    struct node
    {
        int x,y;
        node() {}
        node(int x_,int y_) { x=x_; y=y_;}
    }e[N];
    
    vector<node>empty,f[2];
    
    bool cmp(node p,node q)
    {
        if(p.x!=q.x) return p.x<q.x;
        return p.y<q.y;
    }
    
    int main()
    { 
        int T,n,m,k,mine,l,r,line,tot1,tot2,p;
        long long ans;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d",&n,&m,&k);
            for(int i=1;i<=k;++i) scanf("%d%d",&e[i].x,&e[i].y); 
            sort(e+1,e+k+1,cmp);
            mine=1;
            ans=0;
            line=0;
            f[0].clear();
            f[line].push_back(node(1,1));
            for(int i=1;i<=n;++i)
            {
                line^=1;
                empty.clear();
                f[line].clear(); 
                l=1;
                while(mine<=k && e[mine].x==i)
                {
                    r=e[mine].y-1;
                    if(r>=l) empty.push_back(node(l,r));
                    l=e[mine].y+1;
                    ++mine;
                }
                if(l<=m) empty.push_back(node(l,m));
                tot1=f[line^1].size();
                tot2=empty.size();
                p=0;
                for(int j=0;j<tot2;++j)
                {
                    while(p<tot1 && f[line^1][p].y<empty[j].x) ++p;
                    if(p==tot1 || f[line^1][p].x>empty[j].y) continue;
                    l=max(f[line^1][p].x,empty[j].x);
                    r=empty[j].y;
                    f[line].push_back(node(l,r));
                    ans+=r-l+1;
                }
            }
            printf("%lld
    ",ans);
        }    
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    我不为人人,人人不为我
    sed 小结
    linux 之 压缩 / 解压
    java arraylist的问题
    flex swf和movieclip之前的微妙关系
    Flex contextMenu
    。。
    数据库
    flex Vector
    浮动ip
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15136059.html
Copyright © 2011-2022 走看看