码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2019-11-02 15:23:29      阅读:77      评论:0      收藏:0      [点我收藏+]

标签:continue   signed   turn   size   print   read   getchar   sort   cpp   

题意

\(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;
}

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

标签:continue   signed   turn   size   print   read   getchar   sort   cpp   

原文地址:https://www.cnblogs.com/Chtholly/p/11782389.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!