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

    n<=200000个平面上的点,问有多少对点(i,j)满足Xi<Xj,Yi<Yj,且不存在k使得Xi<Xk<Xj && Yi<Yk<Yj。保证Xi,Yi互不相同。

    看起来像一个偏序问题,先按Xi排序然后分治来做,但是那坨长长的东西怎么搞呢?试了若干种方法,不会,看题解。

    首先Y这一维是要满足的,所以分治时把左右两边按Y归并排序后来看左边对右边的贡献。但是有诸多情况。。。

    实验+总结一下可以观察到下面两个性质:

    (1)

    两边按y排序(从大到小)后,开两个指针扫一扫可以满足条件Yi<Yj,然而并不是所有的都满足,如上图,存在一些遮拦的点。

    由于y是从大到小排序的,可以看一下在左半边把点按y从大到小加进去后会发生什么遮拦情况:

    如图,y从大到小将点加入后,左边若是Yi>Yj却Xi<Xj,那么能被i点(A)拦到的点一定能被j点(B)拦到,因此左半边维护一个Xi随Yi减小而减小的栈,即可找到左边点的互相遮拦限制。如上图中,C点需要在右边找到比B点的y小而比C点的y大的来计算答案。

    (2)看右边点的互相遮拦:

    由于y是从大到小加进去的,新加进的左边的C点的y一定比原来加进的A和B点要小,此时B被A完全拦住。因此右边若Yi>Yj,则必须Xi<Xj,右边维护一个栈即可满足条件3.

    两个栈就完了吗?嗯。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<stdlib.h>
     5 //#include<iostream>
     6 using namespace std;
     7 
     8 int n;
     9 #define maxn 200011
    10 struct Point
    11 {
    12     int x,y;
    13     bool operator < (const Point &b) const {return x<b.x;}
    14 }a[maxn];
    15 
    16 int ord[maxn],tmpord[maxn];
    17 int stal[maxn],topl,star[maxn],topr;
    18 #define LL long long
    19 LL ans=0;
    20 void solve(int L,int R)
    21 {
    22     if (L==R) {ord[L]=L;return;}
    23     const int mid=(L+R)>>1;
    24     solve(L,mid);solve(mid+1,R);
    25     topl=topr=0;
    26     for (int i=L,j=mid+1;i<=mid;i++)
    27     {
    28         while (j<=R && a[ord[j]].y>a[ord[i]].y)
    29         {
    30             while (topr && a[star[topr]].x>a[ord[j]].x) topr--;
    31             star[++topr]=ord[j++];
    32         }
    33         while (topl && a[stal[topl]].x<a[ord[i]].x) topl--;
    34         stal[++topl]=ord[i];
    35         int l=0,r=topr;
    36         while (l<r)
    37         {
    38             const int mid=(l+r+1)>>1;
    39             if (a[star[mid]].y>a[ord[i]].y) l=mid;
    40             else r=mid-1;
    41         }
    42         int up=l,down;
    43         if (topl==1) down=1;
    44         else
    45         {
    46             l=1,r=topr+1;
    47             while (l<r)
    48             {
    49                 const int mid=(l+r)>>1;
    50                 if (a[star[mid]].y<a[stal[topl-1]].y) r=mid;
    51                 else l=mid+1;
    52             }
    53             down=l;
    54         }
    55         ans+=up-down+1;
    56 //        cout<<L<<' '<<R<<' '<<ord[i]<<' '<<ans<<endl;
    57     }
    58     int i=L,j=mid+1,k=L;
    59     while (i<=mid && j<=R)
    60     {
    61         if (a[ord[i]].y>a[ord[j]].y) tmpord[k++]=ord[i++];
    62         else tmpord[k++]=ord[j++];
    63     }
    64     while (i<=mid) tmpord[k++]=ord[i++];
    65     while (j<=R) tmpord[k++]=ord[j++];
    66     for (k=L;k<=R;k++) ord[k]=tmpord[k];
    67 }
    68 
    69 int main()
    70 {
    71     scanf("%d",&n);
    72     for (int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
    73     sort(a+1,a+1+n);
    74 //    for (int i=1;i<=n;i++) cout<<a[i].x<<' '<<a[i].y<<endl;cout<<endl;
    75     solve(1,n);
    76     printf("%lld
    ",ans);
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    SQLITE3在php中的运用
    C# DllImport用法和路径问题
    ExtJs2.0学习系列(9)Ext.TabPanel之第一式
    ExtJs2.0学习系列(11)Ext.XTemplate
    ExtJs2.0学习系列(12)Ext.TreePanel之第一式
    ExtJs2.0学习系列(10)Ext.TabPanel之第二式
    ExtJs2.0学习系列(6)Ext.FormPanel之第三式(ComboBox篇)
    ExtJs2.0学习系列(15)extjs换肤
    ExtJs2.0学习系列(8)Ext.FormPanel之第五式(综合篇)
    ExtJs2.0学习系列(5)Ext.FormPanel之第二式
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7905490.html
Copyright © 2011-2022 走看看