固定一维c,然后(a,b)看成坐标,矩形区域求交
1.Segment tree Beats!
2.改成不合法的区域就是求并,c反向枚举,区域只增不减且完全包含之前的
单调栈预处理找到轮廓线,然后两个指针维护顶头位置即可
#include<bits/stdc++.h> #define reg register int #define il inline #define int long long #define numb (ch^'0') using namespace std; typedef long long ll; il void rd(int &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int N=500000+5; int n,A,B,C; ll ans,sum; struct node{ int a,b,c; }p[N]; bool cmpa(node a,node b){ return a.a<b.a; } bool cmpc(node a,node b){ return a.c>b.c; } int sta[N],top; int x[N],y[N]; int main(){ rd(n);rd(A);rd(B);rd(C); for(reg i=1;i<=n;++i) rd(p[i].a),rd(p[i].b),rd(p[i].c); sort(p+1,p+n+1,cmpa); for(reg i=1;i<=n;++i){ while(top&&p[sta[top]].b<p[i].b) --top; sta[++top]=i; } sum=(ll)A*B; sta[top+1]=0; for(reg i=1;i<=top;++i){ //cout<<" ii "<<i<<" "<<p[sta[i]].b<<endl; sum-=(ll)((ll)p[sta[i]].a-p[sta[i-1]].a)*p[sta[i]].b; for(reg j=p[sta[i-1]].a+1;j<=p[sta[i]].a;++j) x[j]=p[sta[i]].b; for(reg j=p[sta[i]].b;j>p[sta[i+1]].b;--j) y[j]=p[sta[i]].a; } // for(reg i=1;i<=A;++i){ // cout<<x[i]<<" "; // }cout<<endl; // for(reg i=1;i<=B;++i){ // cout<<y[i]<<" "; // }cout<<endl; // cout<<" sum "<<sum<<endl; sort(p+1,p+n+1,cmpc); for(reg tx=1,ty=1,j=1,i=C;i>=1;--i){ // cout<<" i "<<i<<" tx "<<tx<<" ty "<<ty<<endl; while(j<=n&&p[j].c>=i){ // cout<<" p[j] "<<j<<" "<<p[j].c<<endl; for(;tx<=p[j].a;++tx) sum-=B-max(ty-1,x[tx]); // cout<<" sum1 "<<sum<<endl; for(;ty<=p[j].b;++ty) sum-=A-max(tx-1,y[ty]); // cout<<" sum2 "<<sum<<endl; ++j; } ans+=sum; } printf("%lld",ans); return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/3/3 15:45:41 */
很套路了
排序,然后偏序想到坐标矩形求面积
交和并的转化,容斥。或者大力吉司机线段树