zoukankan      html  css  js  c++  java
  • bzoj 4237: 稻草人

    Description

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

    solution

    正解:CDQ分治.
    我们分析满足 (x[i]<x[j],y[i]<y[j]),并且不存在 (k)(x[i]<x[k]<x[j],y[i]<y[k]<y[k])的算作一个满足条件的点对.

    以上二维偏序可以用分治求解,我们可以分治 (x).
    分治中按 (y) 排序,我们考虑 (mid) 左边对 (mid) 右边的贡献:

    左边是作为矩形的左下角,右边作为右上角.

    我们要意识到,在 (mid) 右边 对当前点 (i) 影响最大的一定是 (y)(i) 小,(x)(i) 也小的点,因为 (i) 是作为矩形的右上角,所以这个的点会成为矩形中的点,不会形成矩形,所以我们维护一个 (x) 递增的单调栈,左边维护一个 (x) 递减的单调栈,当前右边的点 (i) ,能够和左边满足(y<=y[i],y>=y[st[top]])的点匹配,然后每一次在左边栈中二分即可,画个图很好理解

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    const int N=200005;
    int n,st[N],top=0,xy[N],pi=0;long long ans=0;
    struct node{
       int x,y;
    }a[N];
    bool comp(const node i,const node j){return i.x<j.x;}
    bool camp(const node i,const node j){return i.y<j.y;}
    void solve(int l,int r){
       if(l==r)return ;
       int mid=(l+r)>>1;
       solve(l,mid);solve(mid+1,r);
       top=0;pi=0;int j=l,li;
       sort(a+l,a+mid+1,camp);sort(a+mid+1,a+r+1,camp);
       for(int i=mid+1;i<=r;i++){
          while(a[j].y<=a[i].y && j<=mid){
             while(top && a[j].x>=a[st[top]].x)top--;
             st[++top]=j;j++;
          }
          while(pi && a[i].x<a[xy[pi]].x)pi--;
          xy[++pi]=i;li=a[xy[pi-1]].y;
          int L=1,R=top,mi,ret=-1;
          while(L<=R){
             mi=(L+R)>>1;
             if(a[st[mi]].y>=li)ret=mi,R=mi-1;
             else L=mi+1;
          }
          if(ret!=-1)ans+=top-ret+1;
       }
    }
    void work()
    {
       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,comp);
       solve(1,n);
       printf("%lld
    ",ans);
    }
    
    int main()
    {
    	work();
    	return 0;
    }
    
    
  • 相关阅读:
    【2018.05.05 C与C++基础】C++中的自动废料收集:概念与问题引入
    【2018.04.27 C与C++基础】关于switch-case及if-else的效率问题
    【2018.04.19 ROS机器人操作系统】机器人控制:运动规划、路径规划及轨迹规划简介之一
    March 11th, 2018 Week 11th Sunday
    March 10th, 2018 Week 10th Saturday
    March 09th, 2018 Week 10th Friday
    March 08th, 2018 Week 10th Thursday
    March 07th, 2018 Week 10th Wednesday
    ubantu之Git使用
    AMS分析 -- 启动过程
  • 原文地址:https://www.cnblogs.com/Hxymmm/p/7702200.html
Copyright © 2011-2022 走看看