• Gym 101666M (线段树)


    传送门

    题面:PDF

    题意:

        给你一个起点s和终点e,有n个地点,问你在不增加从s到e的曼哈顿距离的前提下的能够到达的最多的地点的个数。

    题目分析:

        跟2018CCPC网络赛的一题(HDU 6447)一摸一样,只不过这个题中还需要讨论一下起点和终点的相对位置。

        我们只需要先将y坐标离散化,并根据每个点的x坐标从小到大遍历,并且用线段树对这个点维护它的1到id[y]的最大值即可。

    代码:

    #include <bits/stdc++.h>
    #define maxn 100005
    using namespace std;
    struct ST{
        int maxx;
    }tr[maxn<<2];
    struct Street{
        int x,y,id;
    }q[maxn];
    bool cmp1(Street a,Street b){
        if(a.x==b.x) return a.y<b.y;
        return a.x>b.x;
    }
    bool cmp2(Street a,Street b){
        if(a.x==b.x) return a.y>b.y;
        return a.x>b.x;
    }
    bool cmpy(Street a,Street b){
        return a.y<b.y;
    }
    void push_up(int rt){//线段树维护区间最大值
        tr[rt].maxx=max(tr[rt<<1].maxx,tr[rt<<1|1].maxx);
    }
    void update(int l,int r,int rt,int C,int val){
        if(l==r){
            tr[rt].maxx=val;
            return ;
        }
        int mid=(l+r)>>1;
        if(C<=mid) update(l,mid,rt<<1,C,val);
        else update(mid+1,r,rt<<1|1,C,val);
        push_up(rt);
    }
    int query(int L,int R,int l,int r,int rt){
        if(L<=l&&R>=r) return tr[rt].maxx;
        int mid=(l+r)>>1;
        int maxx=0;
        if(L<=mid) maxx=max(maxx,query(L,R,l,mid,rt<<1));
        if(R>mid) maxx=max(maxx,query(L,R,mid+1,r,rt<<1|1));
        return maxx;
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        Street s,e;
        scanf("%d%d%d%d",&s.x,&s.y,&e.x,&e.y);
        if(n==0){
            puts("0");return 0;
        }
        for(int i=1;i<=n;i++) scanf("%d%d",&q[i].x,&q[i].y);
        //坐标离散化
        sort(q+1,q+1+n,cmpy);
        int cnt=2,yy=q[1].y;
        q[1].id=cnt;
        for(int i=2;i<=n;i++){
            if(yy==q[i].y) q[i].id=cnt;
            else yy=q[i].y,q[i].id=++cnt;
        }
        if(s.x>e.x) swap(s,e);
        if(s.y>e.y){//起始点在终点的左下
            sort(q+1,q+1+n,cmp1);
            for(int i=1;i<=n;i++){
                if(q[i].x<s.x||q[i].x>e.x) continue;
                if(q[i].y<e.y||q[i].y>s.y) continue;
                //查询1到idy[i]的最大值
                int tmp=query(1,q[i].id,1,cnt,1);
                //加上一个的点对答案的影响
                update(1,cnt,1,q[i].id,tmp+1);
            }
        }
        else{//起始点在终点的右上
            sort(q+1,q+1+n,cmp2);//同理上面
            for(int i=1;i<=n;i++){
                if(q[i].x<s.x||q[i].x>e.x) continue;
                if(q[i].y<s.y||q[i].y>e.y) continue;
                int tmp=query(q[i].id,cnt,1,cnt,1);
                update(1,cnt,1,q[i].id,tmp+1);
            }
        }
        cout<<query(1,cnt,1,cnt,1)<<endl;
    }
  • 相关阅读:
    CSS外边距的合并
    四大主流浏览器内核
    ViewPort视口
    url、src、href定义以及使用区别
    Debug和Release区别
    基线概念
    浅谈C#循环控制流程语句(web前端基础)
    With you With me
    css元素内容基础
    年轻人有梦想,老人有回忆
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007200.html
Copyright © 2020-2023  润新知