如果没有修改,那这就是一个经典的二维数点问题,将询问容斥然后扫描线+树状数组即可.
有修改的情况,使用CDQ基于时间分治,变成没有修改的情况.
时间复杂度$\mathcal O((m+Q)\log (m+Q)\log W)$
PS:询问容斥后查询的两个前缀应分配不同的时间戳,为了正确统计贡献为这些时间戳记录一下是第几个操作即可(代码中的num[]
)
/**********/
#define MAXN 200011
#define MAXW 2000011
struct Query
{
ll x,y1,y2,k,dex;
bool operator <(const Query& t)const
{
if(x==t.x)return y2<t.y2;
return x<t.x;
}
}a[MAXN];
struct BIT
{
ll t[MAXW];
#define lowb (i&-i)
void modify(ll i,ll k)
{
while(i<MAXW)t[i]+=k,i+=lowb;
}
ll Qsum(ll i)
{
ll res=0;
while(i)res+=t[i],i-=lowb;
return res;
}
}t;
ll ans[MAXN],is_query[MAXN],num[MAXN];
void CDQ(un l,un r)
{
if(l==r)return;
un mid=(l+r)>>1;
CDQ(l,mid),CDQ(mid+1,r);
std::sort(a+l,a+r+1);
for(ll i=l;i<=r;++i)
if(!a[i].y2)
{
if(a[i].dex<=mid)t.modify(a[i].y1,a[i].k);
}
else
{
if(a[i].dex>mid)ans[num[a[i].dex]]+=(t.Qsum(a[i].y2)-t.Qsum(a[i].y1))*a[i].k;
}
for(ll i=l;i<=r;++i)
if(!a[i].y2&&a[i].dex<=mid)t.modify(a[i].y1,-a[i].k);
}
int main()
{
ll s=read(),w=read(),all=0,dex=0,op;
while((op=read())!=3)
{
++dex;
if(op==1)
{
ll x=read(),y=read(),k=read();
a[++all]={x,y,0,k,all};
}
else
{
is_query[dex]=1;
ll x1=read(),y1=read(),x2=read(),y2=read();
a[++all]={x1-1,y1-1,y2,-1,all};num[all]=dex;
a[++all]={x2,y1-1,y2,1,all};num[all]=dex;
}
}
CDQ(1,all);
for(ll i=1;i<=dex;++i)
if(is_query[i])printf("%d\n",ans[i]);
return 0;
}