zoukankan      html  css  js  c++  java
  • 刷题总结——稻草人(bzoj4237cdq分治)

    题目:

    Description

    JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典。
    有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地。和启示中的一样,田地需要满足以下条件:
    田地的形状是边平行于坐标轴的长方形;
    左下角和右上角各有一个稻草人;
    田地的内部(不包括边界)没有稻草人。
    给出每个稻草人的坐标,请你求出有多少遵从启示的田地的个数

    Input

    第一行一个正整数N,代表稻草人的个数
    接下来N行,第i行(1<=i<=N)包含2个由空格分隔的整数Xi和Yi,表示第i个稻草人的坐标

    Output

    输出一行一个正整数,代表遵从启示的田地的个数

    Sample Input

    4
    0 0
    2 2
    3 4
    4 3

    Sample Output

    3

    HINT

    所有满足要求的田地由下图所示:

     

    1<=N<=2*10^5

    0<=Xi<=10^9(1<=i<=N)

    0<=Yi<=10^9(1<=i<=N)

    Xi(1<=i<=N)互不相同。

    Yi(1<=i<=N)互不相同。

    题解:

      首先每次分治前将点按y轴排序,消除y轴的影响,然后分为上下两部分,分别按x轴排序···

      然后用两个单调栈分别维护上部分和下部分,上部分保证y单调递增,下部分保证y单调递减,这样每次将上部分的点作为右上角,找下部分符的点的数量

      由于是按y轴排序且用了单调栈,我们已经排除了y轴的影响,只用找x轴符合情况的点,这时利用我们已经按x轴排的序,直接二分即可

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=2e5+5;
    struct node
    {
      int x,y;
    }p[N];
    int n,stack1[N],top1,stack2[N],top2;
    long long ans=0;
    inline bool cmpy(node a,node b)
    {
      return a.y<b.y;
    }
    inline bool cmpx(node a,node b)
    {
      return a.x<b.x;
    }
    inline int R()
    {
      char c;int f=0;
      for(c=getchar();c<'0'||c>'9';c=getchar());
      for(;c<='9'&&c>='0';c=getchar())
        f=(f<<3)+(f<<1)+c-'0';
      return f;
    }
    inline void solve(int l,int r)
    { 
      if(l==r)  return;
      int mid=(l+r)/2;top1=top2=0;
      sort(p+l,p+r+1,cmpy);
      sort(p+l,p+mid+1,cmpx);sort(p+mid+1,p+r+1,cmpx);
      int j=l;
      for(int i=mid+1;i<=r;i++)
      {
        while(top1&&p[stack1[top1]].y>=p[i].y)  top1--;
        stack1[++top1]=i;
        while(j<=mid&&p[j].x<p[i].x)  
        {
          while(top2&&p[stack2[top2]].y<=p[j].y) top2--;
          stack2[++top2]=j;
          j++;
        }
        int st=p[stack1[top1-1]].x;
        int le=1,ri=top2,anss=-1;
        while(le<=ri)
        {
          int mi=(le+ri)/2; 
          if(p[stack2[mi]].x>st)  anss=mi,ri=mi-1;
          else le=mi+1;
        }
        if(anss!=-1)
          ans+=top2-anss+1;
      }
      solve(l,mid),solve(mid+1,r);
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      n=R();
      for(int i=1;i<=n;i++)
        p[i].x=R(),p[i].y=R();
      p[0].x=-1,p[0].y=-1;
      solve(1,n);
      printf("%lld",ans);
      return 0;
    }

    注意两个细节:

    一是每次分治前都要按y轴排序

    二是插入一个xy均为-1的点,不然后面二分时会出错

  • 相关阅读:
    「ZJOI2019」&「十二省联考 2019」题解索引
    jmeter测试20个QPS下的响应时间-设置QPS限制
    Postman的基础使用
    Selenium如何定位动态id的元素?
    python+selenium:iframe框架中多种定位
    关于正则表达式
    项目关键路径
    paycharm导入webdriver包报错:module 'selenium.webdriver' has no attribute 'Firefox'
    随着firefox的迭代更新:FireBug不能用了?使用火狐Try Xpath插件替代Firebug和Firepath
    Python——连接操作数据库
  • 原文地址:https://www.cnblogs.com/AseanA/p/7531698.html
Copyright © 2011-2022 走看看