bzoj 4237稻草人
按x轴进行分治,将[l,r]分成[l,mid]和[mid+1,r],左下角点x值在[l,mid]中,右上角点x值在[mid+1,r],然后将[l,r]中的所有点按y轴排序,按顺序扫描,若扫描到左下角点,用一个单调栈维护,若扫描到右上角点,用另一个单调栈维护的同时,去维护左下角的单调栈中二分出答案,复杂度O(nlognlogn),程序跑的有点慢
代码
1 #include<cstdio> 2 #include<algorithm> 3 #include<set> 4 #define N 500010 5 using namespace std; 6 int n,i; 7 long long ans; 8 int top1,top2,stack1[N],stack2[N]; 9 struct g{ 10 int x,y; 11 }a[N]; 12 bool cmp(g a,g b) 13 { 14 return a.x<b.x; 15 } 16 bool cmp1(g a,g b) 17 { 18 return a.y<b.y; 19 } 20 int ef(int x) 21 { 22 int l=1,r=top1,m; 23 while (l<=r) 24 { 25 m=(l+r)>>1; 26 if (x>a[stack1[m]].y) l=m+1;else r=m-1; 27 } 28 return r; 29 } 30 void solve(int L,int R,int l,int r) 31 { 32 int p,q; 33 if (L>=R) return; 34 if (l>=r) return; 35 int m=(L+R)>>1; 36 int cnt=l,i; 37 int t; 38 for (i=l;i<=r;i++) 39 if (a[i].x<=m) 40 { 41 t=a[i].x;a[i].x=a[cnt].x;a[cnt].x=t; 42 t=a[i].y;a[i].y=a[cnt].y;a[cnt].y=t; 43 cnt++; 44 } 45 46 if ((l<cnt)&&(cnt<=r)) 47 { 48 sort(a+l,a+cnt,cmp1); 49 sort(a+cnt,a+1+r,cmp1); 50 51 top1=0;top2=0; 52 p=l;q=cnt; 53 while ((p<cnt)||(q<=r)) 54 { 55 if ((p==cnt)||((q<=r)&&(a[q].y<a[p].y))) 56 { 57 while ((top2)&&(a[q].x<a[stack2[top2]].x)) top2--; 58 ans+=ef(a[q].y)-ef(a[stack2[top2]].y); 59 top2++;stack2[top2]=q;q++; 60 } 61 else 62 { 63 while ((top1)&&(a[p].x>a[stack1[top1]].x)) top1--; 64 top1++;stack1[top1]=p;p++; 65 } 66 } 67 68 } 69 /* 70 printf("%d %d\n",L,R); 71 printf("A:\n"); 72 for (i=l;i<cnt;i++) 73 printf("%d %d\n",a[i].x,a[i].y); 74 printf("B:\n"); 75 for (i=cnt;i<=r;i++) 76 printf("%d %d\n",a[i].x,a[i].y); 77 */ 78 solve(L,m,l,cnt-1); 79 solve(m+1,R,cnt,r); 80 } 81 int main() 82 { 83 scanf("%d",&n); 84 for (i=1;i<=n;i++) 85 { 86 scanf("%d%d",&a[i].x,&a[i].y); 87 a[i].y++; 88 } 89 sort(a+1,a+1+n,cmp); 90 for (i=1;i<=n;i++) 91 a[i].x=i; 92 solve(1,n,1,n); 93 printf("%lld\n",ans); 94 }