hdu5200 Trees(逆向思维+离线处理)

来源:互联网 发布:苹果电脑软件如何升级 编辑:程序博客网 时间:2024/04/28 00:20

题意描述:

在一条直线上有n棵树,每棵树有一个高度。现在进行查询:给一个高度h,把小于等于h的树砍掉,剩余的树能组成几个块?

块的定义:一个块要包含尽可能多的位置连续的树,而且被包含的树没有被砍掉


解题思路:离线处理

1、逆向思维:砍树的对立面就是长树

                (1)如果我们把树的高度和查询高度都按从大到小的顺序排序,初始化直线上没有一棵树存在;

                (2)然后从前往后扫描查询,对于当前查询,我们只需要把高于当前查询的树生长出来(vis数组标记即可)

(3)在每颗树生长的同时检测其两边的树是否已经生长,对于不同的情况分类讨论即可

源代码:

#include <cstdio>#include <cstring>#include <algorithm>#define MAXN 50010using namespace std;struct node{    int h;    int index;};bool cmp(node a,node b){    return a.h>b.h;}node d[MAXN];///树的高度node q[MAXN];///查询高度bool vis[MAXN];///标记树是否已经生长int ans[MAXN];///每个查询的连通块int n,m;int main(){    while(scanf("%d%d",&n,&m)!=EOF){        for(int i=0;i<n;++i)        {            scanf("%d",&d[i].h);            d[i].index=i;        }        sort(d,d+n,cmp);        for(int i=0;i<m;++i){            scanf("%d",&q[i].h);            q[i].index=i;        }        sort(q,q+m,cmp);        int id=0,iq=0;        int tans=0;        memset(vis,false,sizeof(vis));        while(iq<m){            if(id<n){                if(q[iq].h>=d[id].h){///没有可以生长的树                    ans[q[iq].index]=tans;                    iq++;                }                else{                    for(;id<n&&d[id].h>q[iq].h;++id){                        int tl=d[id].index-1;                        int tr=d[id].index+1;                        if(tl>=0&&tr<n&&vis[tl]&&vis[tr])///如果树两边的树都已经生长,加上这棵树之后构成一个块,由2变为1                            tans--;                        ///两边的树如果都还没有生长,则块+1                        if(tl>=0){                            if(!vis[tl]){                                if(tr<n){                                    if(!vis[tr])                                        tans++;                                }                                else                                    tans++;                            }                        }                        else{                            if(tr<n){                                if(!vis[tr])                                    tans++;                            }                            else                                tans++;                        }                        vis[tl+1]=true;                    }                    ans[q[iq].index]=tans;                }            }            else///所有的树已经生长完            {                ans[q[iq].index]=tans;                iq++;            }        }        for(int i=0;i<m;++i)            printf("%d\n",ans[i]);    }    return 0;}

2、正向思维:

    1、我们把树的高度和查询高度从小到大排序,从前往后处理每个查询,初始化直线上的所有树都在

    2、对于当前查询,我们只需要把小于等于查询高度的树砍掉即可

    3、对于每次砍树,检测其两边的树是否被砍掉,分类讨论即可


0 0
原创粉丝点击