zoukankan      html  css  js  c++  java
  • bzoj4237 稻草人——分治

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4237

    分治;

    先把所有点按 y 排序,然后二分递归;

    对于每个 mid ,计算经过它的矩形的个数,把上面的每个点当做右上角,考虑下面多少点可以作为左下角;

    上面的限制只有前面的 y 大于等于自己的 y,所以维护递增的单调栈;

    下面的限制是后面的 y 小于等于自己的 y,所以维护递减的单调栈;

    还要注意 x 的限制,二分找到栈内满足条件的最前面的点,到栈顶的元素个数就是对答案的贡献。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int const maxn=2e5+5;
    int n,tpa,tpb,sta[maxn],stb[maxn];
    long long ans;
    struct N{int x,y;}s[maxn];
    bool cmp(N a,N b){return a.y<b.y;}
    bool cmpx(N a,N b){return a.x<b.x;}
    void cdq(int l,int r)
    {
        if(l==r)return;
        int mid=((l+r)>>1);
        cdq(l,mid); cdq(mid+1,r);
        sort(s+l,s+mid+1,cmpx); sort(s+mid+1,s+r+1,cmpx);//请不要写成 s+1 
        int p=l; tpa=tpb=0;
        for(int i=mid+1;i<=r;i++)
        {
            while(s[sta[tpa]].y>=s[i].y && tpa)tpa--;
            int pos=s[sta[tpa]].x; sta[++tpa]=i;
            while(p<=mid && s[p].x<s[i].x)
            {
                while(s[stb[tpb]].y<=s[p].y && tpb)tpb--;
                stb[++tpb]=p; p++;
            }
            int L=1,R=tpb,res=-1;
            while(L<=R)
            {
                int Mid=((L+R)>>1);
                if(s[stb[Mid]].x>pos)res=Mid,R=Mid-1;
                else L=Mid+1;
            }
            if(res!=-1)ans+=tpb-res+1;
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&s[i].x,&s[i].y);
        s[0].x=s[0].y=-1;//
        sort(s+1,s+n+1,cmp);
        cdq(1,n);
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    [Leetcode] 225. Implement Stack using Queues
    前端面试题2
    数据结构_stack
    数据结构 station
    数据结构_wow(泡泡的饭碗)
    数据结构_XingYunX(幸运儿)
    数据结构 nxd(顺序对)
    数据结构 hbb(汉堡包)
    数据结构 elegant_sequence(优雅的序列)
    数据结构 i_love(我喜欢)
  • 原文地址:https://www.cnblogs.com/Zinn/p/9231373.html
Copyright © 2011-2022 走看看