Loj#2880-「JOISC 2014 Day3」稻草人【CDQ分治,单调栈,二分】
阅读原文时间:2023年07月08日阅读:1

正题

题目链接:https://loj.ac/problem/2880


给出平面上的\(n\)个点,然后求有多少个矩形满足

  1. 左下角和右上角各有一个点
  2. 矩形之间没有其他点

\(1\leq n\leq 2\times 10^5,1\leq x_i,y_i\leq 10^9,\)保证\(x_i,y_i\)分别不重复出现。


按照\(x\)排序,考虑\(CDQ\)分治后左边对右边的影响,对\(y\)从大到小排序然后左右各自维护一个单调栈,左边考虑每个点第一个右上角的点,右边维护一个\(y\)轴递减,\(x\)轴递增的单调栈,然后再右边的单调栈上二分出左边的合法位置即可。

时间复杂度\(O(n\log^2 n)\)


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e5+10;
struct node{
    int x,y;
}p[N];
int n,s[N],t[N];
long long ans;
bool cmp(node x,node y){return x.x<y.x;}
bool cMp(node x,node y){return x.y>y.y;}
void CDQ(int l,int r){
    if(l==r)return;
    int mid=(l+r)>>1;
    CDQ(l,mid);
    CDQ(mid+1,r);
    sort(p+l,p+mid+1,cMp);
    sort(p+mid+1,p+r+1,cMp);
    int z=mid+1,top=0,toq=0;
    for(int i=l;i<=mid;i++){
        while(z<=r&&p[z].y>=p[i].y){
            while(top>0&&p[z].x<p[s[top]].x)top--;
            s[++top]=z;z++;
        }
        while(toq>0&&p[i].x>p[t[toq]].x)toq--;
        if(toq){
            int L=1,R=top;
            while(L<=R){
                int mid=(L+R)>>1;
                if(p[s[mid]].y>p[t[toq]].y)L=mid+1;
                else R=mid-1;
            }
            ans+=top-L+1;
        }
        else ans+=top;
        t[++toq]=i;
    }
    return;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&p[i].x,&p[i].y);
    sort(p+1,p+1+n,cmp);
    CDQ(1,n);
    printf("%lld\n",ans);
    return 0;
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章