[CSP校内集训]矩形面积交(树状数组)
题意
给\(n\)个互不相交的矩形,再给\(m\)个询问,每次给一个矩形求它与这\(n\)个矩形的面积交
思路
自己写的太丑了导致DEBUG了一个半小时qwq
一对矩形的交可以拆分成二维前缀和形式下的矩形的交,于是变成判断16次矩形的交(不想画图...只想口胡)
这些矩形都有\(x_0=0,y_0=0\),即左下角为坐标原点,于是一个矩形可以只用右上角的坐标表示;
对于一个询问的矩形\((x,y)\)和另一个矩形\((x_i,y_i)\),它们的交为\(min(x,x_i)\times min(y,y_i)\)
对\(x\)排序,分类讨论\(y\leq y_i\)和\(y>y_i\),用树状数组维护即可
Code
#include<bits/stdc++.h>
#define N 500005
#define int ll
#define lowbit(x) ((x)&(-(x)))
#define Min(x,y) ((x)<(y)?(x):(y))
#define Max(x,y) ((x)>(y)?(x):(y))
using namespace std;
typedef long long ll;
int n,m,w,l,cnt0,cnt;
ll sum[N],sumy[N],sumx[N],c[N];
struct Matrix { int x,y,opt; } ma[N<<2];
struct Query { int x,y,id,opt; ll ans; } q[N<<2];
template <class T>
void read(T &x)
{
char c; int sign=1;
while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48; x*=sign;
}
void ad(int id,int opt,int x,int y)
{
++cnt;
q[cnt].id=id; q[cnt].opt=opt;
q[cnt].x=x; q[cnt].y=y;
}
void modify_1(int x,int val) { for(;x<N;x+=lowbit(x)) c[x]+=val; }
void modify_2(int x,ll val) { for(;x<N;x+=lowbit(x)) sum[x]+=val; }
void modify_3(int x,ll val) { for(;x<N;x+=lowbit(x)) sumy[x]+=val; }
void modify_4(int x,ll val) { for(;x<N;x+=lowbit(x)) sumx[x]+=val; }
ll query_1(int x) { ll ret=0; for(;x;x-=lowbit(x)) ret+=c[x]; return ret;}
ll query_2(int x) { ll ret=0; for(;x;x-=lowbit(x)) ret+=sum[x]; return ret;}
ll query_3(int x) { ll ret=0; for(;x;x-=lowbit(x)) ret+=sumy[x]; return ret;}
ll query_4(int x) { ll ret=0; for(;x;x-=lowbit(x)) ret+=sumx[x]; return ret;}
void update(Matrix a)//加入矩阵a
{
modify_1(a.y,a.opt);
modify_2(a.y,a.opt*(a.x*a.y));
modify_3(a.y,a.opt*a.y);
modify_4(a.y,a.opt*a.x);
}
bool cmp1(Matrix a,Matrix b) { return a.x<b.x; }
bool cmp2(Query a,Query b) { return a.x<b.x; }
bool cmp3(Query a,Query b) { return a.id<b.id; }
signed main()
{
freopen("intersec.in","r",stdin);
freopen("intersec.out","w",stdout);
read(n);read(m);read(w);read(l);
for(int i=1;i<=n;++i)
{
int x[2],y[2];
read(x[0]);read(y[0]);
read(x[1]);read(y[1]);
ma[++cnt0]=(Matrix){x[1],y[1],1};
ma[++cnt0]=(Matrix){x[0],y[1],-1};
ma[++cnt0]=(Matrix){x[1],y[0],-1};
ma[++cnt0]=(Matrix){x[0],y[0],1};
}
for(int i=1;i<=m;++i)
{
int x[2],y[2];
read(x[0]);read(y[0]);
read(x[1]);read(y[1]);
ad(i,1,x[1],y[1]);
ad(i,-1,x[0],y[1]);
ad(i,-1,x[1],y[0]);
ad(i,1,x[0],y[0]);
}
sort(ma+1,ma+cnt0+1,cmp1);
sort(q+1,q+cnt+1,cmp2);
int L=0;//加入了L个矩阵
for(int i=1;i<=cnt;++i)//处理第i个询问矩阵
{
if(q[i].x==0||q[i].y==0) continue;
while(L<cnt0&&ma[L+1].x<=q[i].x)
{
++L;
if(ma[L].x>0&&ma[L].y>0) update(ma[L]);
}
q[i].ans+=(query_2(q[i].y) + q[i].y*(query_4(N-1)-query_4(q[i].y)));
}
memset(c,0,sizeof(c));
memset(sum,0,sizeof(sum));
memset(sumx,0,sizeof(sumx));
memset(sumy,0,sizeof(sumy));
int R=cnt0+1;
for(int i=cnt;i>=1;--i)
{
if(q[i].x==0||q[i].y==0) continue;
while(R>1&&ma[R-1].x>q[i].x)
{
--R;
if(ma[R].x>0&&ma[R].y>0) update(ma[R]);
}
q[i].ans+=q[i].x * (query_3(q[i].y) + (query_1(N-1)-query_1(q[i].y))*q[i].y);
}
sort(q+1,q+cnt+1,cmp3);
for(int i=1;i<=cnt;i+=4)
{
ll ans=0;
for(int j=0;j<4;++j) ans+=q[i+j].opt*q[i+j].ans;
printf("%lld\n",ans);
}
return 0;
}