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\n",ans);
    }    
}

 

posted @ 2021-08-13 10:07  TRTTG  阅读(62)  评论(0编辑  收藏  举报