[CSP校内集训]矩形面积交(树状数组)

Posted chtholly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CSP校内集训]矩形面积交(树状数组)相关的知识,希望对你有一定的参考价值。

题意

(n)个互不相交的矩形,再给(m)个询问,每次给一个矩形求它与这(n)个矩形的面积交

思路

自己写的太丑了导致DEBUG了一个半小时qwq

一对矩形的交可以拆分成二维前缀和形式下的矩形的交,于是变成判断16次矩形的交(不想画图...只想口胡)

这些矩形都有(x_0=0,y_0=0),即左下角为坐标原点,于是一个矩形可以只用右上角的坐标表示;

对于一个询问的矩形((x,y))和另一个矩形((x_i,y_i)),它们的交为(min(x,x_i) imes min(y,y_i))

(x)排序,分类讨论(yleq 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
",ans);
    }
    return 0;
}

以上是关于[CSP校内集训]矩形面积交(树状数组)的主要内容,如果未能解决你的问题,请参考以下文章

[CSP-S模拟测试]:Rectangle(模拟+树状数组)

[CSP校内集训]attack(DAG支配树)

[CSP校内集训]tree(期望DP)

[CSP校内集训]pestc(拓扑排序)

[CSP校内集训]贪吃蛇(阿尔法-贝塔剪枝)

bzoj5173[Jsoi2014]矩形并 扫描线+二维树状数组区间修改区间查询