bzoj4237稻草人

题意:给你一个田地,问左下角和右上角有稻草人并且内部除了边界都没有稻草人的矩形数。

 

标程:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int read()
 4 {
 5    int x=0,f=1;char ch=getchar();
 6    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
 7    while (ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
 8    return x*f;
 9 }
10 const int N=200005;
11 int n,q1[N],q2[N];
12 long long ans;
13 struct node{int x,y;}a[N],tmp[N];
14 bool cmp(const node &A,const node &B) {return A.y<B.y;}
15 int find(int x,int l,int r)
16 {
17    while (l+1<r)
18    {
19          int mid=(l+r)/2;
20       if (a[q2[mid]].x<x) l=mid;else r=mid;//边界上的点不算 
21    }
22    return l;
23 }
24 void solve(int l,int r)
25 {
26     if (l==r) return;
27     int mid=((l+r)>>1);
28     solve(l,mid);solve(mid+1,r);
29     int top1=0,top2=0;
30     for (int i=mid+1,j=l;i<=r;i++)
31     {
32       while (top1&&a[i].y<a[q1[top1]].y) top1--;
33       for (;j<=mid&&a[j].x<a[i].x;j++)//勿取等号,一条线不算矩形 
34       {
35            while (top2&&a[j].y>a[q2[top2]].y) top2--;
36            q2[++top2]=j;
37       }
38       ans+=top2-find(a[q1[top1]].x,0,top2+1);//二分边界注意 
39       q1[++top1]=i;
40     }
41     int L=l,R=mid+1;
42     for (int i=l;i<=r;i++)
43       if (R>r||a[L].x<a[R].x&&L<=mid) tmp[i]=a[L++];else tmp[i]=a[R++];
44     for (int i=l;i<=r;i++) a[i]=tmp[i];
45 }
46 int main()
47 {
48     n=read();
49     for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();
50     sort(a+1,a+n+1,cmp);
51     solve(1,n);
52     printf("%lld\n",ans);
53     return 0;
54 }
View Code

 

题解:cdq分治+单调栈+二分

第一感觉李超树也能做吧。维护折点个数。

那么同理上次一道李超树考试题也可以用cdq分治,二分之前预处理前缀和。

将稻草人平面分成上下两块,按照x坐标排序,枚举上部的一个点作为右上角,在下半部分统计有多少个y坐标依次递减的左下角,并且满足比上部离右上角最近的点x坐标更大。上下都用单调栈维护,最后二分可行的左下角。

时间复杂度O(nlog^2(n))。

注意二分的时候边界条件,从0~top2+1。

转载于:https://www.cnblogs.com/Scx117/p/9201710.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值