思路
考虑每个修改对每个询问的贡献。
直接做询问矩形与修改三角形的交比较复杂。将一次修改差分为两个没有左边界的等腰三角形和两个没有左/下边界矩形,将询问差分为四个没有右/上边界的矩形。这样询问和修改的交都只是等腰三角形。
对于修改 1 x y w d
,差分成 和 为右下角的等腰三角形,和 和 为右上角的矩形。
考虑把修改/查询放在端点上,如果满足时间维、两个空间维的偏序关系就会有贡献,贡献可以拆为至多 项。cdq 分治即可。
code
int q,id=1;
struct node{
int x,y,w,t,op;
}upd1[maxn<<1],upd2[maxn<<1],a[maxn*6],b[maxn*6];
int lsh[maxn<<2],len,tot1,tot2,n;
int ans[maxn];
struct bit{
int tree[maxn<<2];
#define lb(x) (x&(-x))
void upd(int x,int w){
while(x<=len)tree[x]+=w,x+=lb(x);
}
int que(int x){
int res=0;
while(x)res+=tree[x],x-=lb(x);
return res;
}
int que(int l,int r){return que(r)-que(l-1);}
}t0,t1,t2,t3;
void cdq1(int l,int r){
if(l==r)return ;
int mid=l+r>>1;
cdq1(l,mid),cdq1(mid+1,r);
auto cmp=[&](node u,node v){return u.x>v.x||(u.x==v.x&&u.y>v.y)||(u.x==v.x&&u.y==v.y&&u.op<v.op);};
auto upd=[&](int x,int y,int w){
t0.upd(y,w);
t1.upd(y,x*w);
t2.upd(y,x*x*w);
};
for(int i=mid+1,j=l;i<=r;i++){
while(j<=mid&&cmp(a[j],a[i])){
if(!a[j].op)upd(a[j].x,a[j].y,a[j].w);
j++;
}
if(a[i].op){
ans[a[i].t]+=a[i].w*(t2.que(a[i].y,len)-(a[i].x*2-3)*t1.que(a[i].y,len)+(a[i].x-1)*(a[i].x-2)*t0.que(a[i].y,len));
}
if(i==r){
for(int k=l;k<j;k++)if(!a[k].op)upd(a[k].x,a[k].y,-a[k].w);
}
}
for(int i=l,j=mid+1,p=l;i<=mid&&j<=r;){
if(cmp(a[i],a[j]))b[p++]=a[i++];
else b[p++]=a[j++];
if(i==mid+1){
while(j<=r)b[p++]=a[j++];
}
if(j==r+1){
while(i<=mid)b[p++]=a[i++];
}
}
for(int i=l;i<=r;i++)a[i]=b[i];
}
void cdq2(int l,int r){
if(l==r)return ;
int mid=l+r>>1;
cdq2(l,mid),cdq2(mid+1,r);
auto cmp=[&](node u,node v){return u.x>v.x||(u.x==v.x&&u.y<v.y);};
auto upd=[&](int x,int y,int w){
t0.upd(y,w);
t1.upd(y,x*w);
t2.upd(y,x*x*w);
};
for(int i=mid+1,j=l;i<=r;i++){
while(j<=mid&&cmp(a[j],a[i])){
if(!a[j].op)upd(a[j].x,a[j].y,a[j].w);
j++;
}
if(a[i].op){
ans[a[i].t]+=a[i].w*(t2.que(1,a[i].y-1)-(a[i].x*2-3)*t1.que(1,a[i].y-1)+(a[i].x-1)*(a[i].x-2)*t0.que(1,a[i].y-1));
}
if(i==r){
for(int k=l;k<j;k++)if(!a[k].op)upd(a[k].x,a[k].y,-a[k].w);
}
}
for(int i=l,j=mid+1,p=l;i<=mid&&j<=r;){
if(cmp(a[i],a[j]))b[p++]=a[i++];
else b[p++]=a[j++];
if(i==mid+1){
while(j<=r)b[p++]=a[j++];
}
if(j==r+1){
while(i<=mid)b[p++]=a[i++];
}
}
for(int i=l;i<=r;i++)a[i]=b[i];
}
void cdq3(int l,int r){
if(l==r)return ;
int mid=l+r>>1;
cdq3(l,mid),cdq3(mid+1,r);
auto cmp=[&](node u,node v){return u.x>v.x||(u.x==v.x&&u.y>v.y)||(u.x==v.x&&u.y==v.y&&u.op<v.op);};
auto upd=[&](int x,int y,int w){
t0.upd(y,w);
t1.upd(y,x*w);
t2.upd(y,lsh[y]*w);
t3.upd(y,x*lsh[y]*w);
};
for(int i=mid+1,j=l;i<=r;i++){
while(j<=mid&&cmp(a[j],a[i])){
if(!a[j].op)upd(a[j].x,a[j].y,a[j].w);
j++;
}
if(a[i].op){
ans[a[i].t]+=2*a[i].w*(t3.que(a[i].y,len)-(a[i].x-1)*t2.que(a[i].y,len)-(lsh[a[i].y]-1)*t1.que(a[i].y,len)+(a[i].x-1)*(lsh[a[i].y]-1)*t0.que(a[i].y,len));
}
if(i==r){
for(int k=l;k<j;k++)if(!a[k].op)upd(a[k].x,a[k].y,-a[k].w);
}
}
for(int i=l,j=mid+1,p=l;i<=mid&&j<=r;){
if(cmp(a[i],a[j]))b[p++]=a[i++];
else b[p++]=a[j++];
if(i==mid+1){
while(j<=r)b[p++]=a[j++];
}
if(j==r+1){
while(i<=mid)b[p++]=a[i++];
}
}
for(int i=l;i<=r;i++)a[i]=b[i];
}
void work(){
q=read();
while(q--){
int op=read();
if(op==1){
int x=read(),y=read(),d=read(),w=read();
upd1[++tot1]={x+d-1,y,w,id,0},upd1[++tot1]={x-1,y+d,-w,id,0};
upd2[++tot2]={x-1,y+d-1,-w,id,0},upd2[++tot2]={x-1,y-1,w,id,0};
lsh[++len]=y,lsh[++len]=y+d,lsh[++len]=y+d-1,lsh[++len]=y-1;
}
else{
int x=read(),u=read(),y=read(),v=read();
a[++n]={x,y,1,id,1},a[++n]={u+1,v+1,1,id,1};
a[++n]={x,v+1,(int)-1,id,1},a[++n]={u+1,y,(int)-1,id,1};
lsh[++len]=y,lsh[++len]=v+1;
++id;
}
}
sort(lsh+1,lsh+len+1),len=unique(lsh+1,lsh+len+1)-lsh-1;
for(int i=1;i<=tot1;i++)upd1[i].y=lower_bound(lsh+1,lsh+len+1,upd1[i].y)-lsh;
for(int i=1;i<=tot2;i++)upd2[i].y=lower_bound(lsh+1,lsh+len+1,upd2[i].y)-lsh;
for(int i=1;i<=n;i++)a[i].y=lower_bound(lsh+1,lsh+len+1,a[i].y)-lsh;
for(int i=1;i<=tot1;i++)a[++n]=upd1[i];
auto cmp=[&](node u,node v){
return u.t<v.t||(u.t==v.t&&u.op<v.op)||(u.t==v.t&&u.op==v.op&&u.x>v.x)||(u.t==v.t&&u.op==v.op&&u.x==v.x&&u.y>v.y);
};
auto cmp1=[&](node u,node v){
return u.t<v.t||(u.t==v.t&&u.op<v.op)||(u.t==v.t&&u.op==v.op&&u.x>v.x)||(u.t==v.t&&u.op==v.op&&u.x==v.x&&u.y<v.y);
};
sort(a+1,a+n+1,cmp);
cdq1(1,n);
for(int i=1;i<=n;i++)a[i].x=a[i].x+lsh[a[i].y];
sort(a+1,a+n+1,cmp1);
cdq2(1,n);
for(int i=1;i<=n;i++)a[i].x=a[i].x-lsh[a[i].y];
sort(a+1,a+n+1,[&](node u,node v){return u.op<v.op;});
for(int i=1;i<=tot2;i++)a[i]=upd2[i];
sort(a+1,a+n+1,cmp);
cdq3(1,n);
for(int i=1;i<id;i++)write((ans[i]<<1)>>2),puts("");
}