• [bzoj 4237] 稻草人


    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)互不相同。
    CDQ分治+单调栈+二分搜索
    将所有点按y排序,然后将其分成上下两半,考虑左下角的点在下半部分,右上角的点在上部分的矩形有几个
    我们将这些点按x值从小到大做,遇到一个右边的点i时,我们需要知道第一个y值比它大的左边的点j是哪个,对此我们可以维护一个y值单调递减的栈,将点i加进来后不断弹出在它前面的y值比它小的点。同时我们要维护下半部分一个y值单调递增的栈(类似单调队列),然后统计上边的栈中有多少个点的x值介于x[j]~x[i]之间。当点i作为矩形的左下角时,这些点便可作为矩形的右上角
     
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 struct Node
     7 {
     8     int x,y;
     9 }a[200001];
    10 int s1[200001],s2[200001];
    11 long long ans;
    12 int n;
    13 bool cmpy(Node a,Node b)
    14 {
    15     return (a.y<b.y);
    16 }
    17 bool cmpx(Node a,Node b)
    18 {
    19     return (a.x<b.x);
    20 }
    21 void cdq(int l,int r)
    22 {int j,i,p,top1=0,top2=0;
    23 //cout<<l<<' '<<r<<endl;
    24     if (l==r) return;
    25     int mid=(l+r)/2;
    26     cdq(l,mid);cdq(mid+1,r);
    27     sort(a+l,a+mid+1,cmpx);
    28     sort(a+mid+1,a+r+1,cmpx);
    29     j=l;
    30      for (i=mid+1;i<=r;i++)
    31      {
    32         while (top1&&a[s1[top1]].y>=a[i].y) top1--;
    33         s1[++top1]=i;
    34         while (a[j].x<a[i].x&&j<=mid)
    35         {
    36          while (top2&&a[s2[top2]].y<=a[j].y) top2--;
    37          s2[++top2]=j;
    38           j++;
    39         }
    40         int ll=1,rr=top2,std=a[s1[top1-1]].x,pos=-1;  
    41         //cout<<ll<<' '<<rr<<endl;
    42        while(ll<=rr){  
    43            int mid=(ll+rr)/2;  
    44            if(a[s2[mid]].x>std) pos=mid,rr=mid-1;  
    45            else ll=mid+1;  
    46        }  
    47          //cout<<top2<<' '<<pos<<endl;
    48     if (pos!=-1) ans+=top2-pos+1;
    49      }
    50 }
    51 int main()
    52 {int i;
    53     cin>>n;
    54     a[0].x=a[0].y=-1;
    55     for (i=1;i<=n;i++)
    56     {
    57         scanf("%d%d",&a[i].x,&a[i].y);
    58     }
    59      sort(a+1,a+n+1,cmpy);
    60      cdq(1,n);
    61     cout<<ans;
    62 }
  • 相关阅读:
    “终身幼儿园”:学习是一个创造的过程
    我对ERP实质的理解(陈启申)
    Java学习记录1java并发编程之synchronized初学
    谈谈你对Spring的理解
    java中的==与equals的区别
    Windows下编译安装perl Module
    win系统用virtualBox安装Ubuntu虚拟机,如何共享数据
    Windows下emacsw3m设置代理
    自我介绍
    document 对象
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7406912.html
Copyright © 2020-2023  润新知