BZOJ4237 稻草人 【CDQ分治】

摘要:
乔伊村有一片荒地,上面矗立着N只稻草人。村民们每年都会在稻草人周围举行很多次仪式。有一次,乔伊村的村长听到了稻草人的灵感,打算在荒地上开垦一块土地。正如在启示录中,场需要满足以下条件:场的形状是一个矩形,其边与坐标轴平行;左下角和右上角分别有一个稻草人;田野里没有稻草人。

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值就好了

#include<bits/stdc++.h>
using namespace std;
#define N 200010
#define LL long long
int n,p[N],q[N];
struct Node{int x,y;}a[N];LL ans=0;
bool cmp1(Node a,Node b){return a.y<b.y;}
bool cmp2(Node a,Node b){return a.x<b.x;}
int find(int val,int l,int r){
    while (l+1<r){
        int mid=(l+r)>>1;
        if (a[q[mid]].x<val)l=mid;
        else r=mid;
    }
    return l;
}
void solve(int l,int r){
    if(l==r)return;
    int mid=(l+r)>>1;
    solve(l,mid);
    solve(mid+1,r);
    sort(a+l,a+mid+1,cmp2);
    sort(a+mid+1,a+r+1,cmp2);
    int tp=0,tq=0,tmp=l;
    for(int i=mid+1;i<=r;i++){
        while(tp&&a[i].y<a[p[tp]].y)tp--;
        p[++tp]=i;
        while(a[tmp].x<a[i].x&tmp<=mid){
            while(tq&&a[tmp].y>a[q[tq]].y)tq--;
            q[++tq]=tmp;
            tmp++;
        }
        ans+=tq-find(a[p[tp-1]].x,0,tq+1);
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
    sort(a+1,a+n+1,cmp1);
    solve(1,n);
    printf("%lld
",ans);
    return 0;
}

免责声明:文章转载自《BZOJ4237 稻草人 【CDQ分治】》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇sqlplus 汉字乱码问题的解决Linux主机加固下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章