题目链接
一个修改操作对一个查询操作的影响可以O(1)算。每次修改维护一个差分数
组,每一次复杂度 O(n)。
然后,每k次修改操作以后就重构整个三角形。
这样每次询问的话对于单个修改操作的查询用时就是 K。
然后每次重构时通过差分数组还原出原数组。再求出前缀和。用时是n^2=10^6。
每次查询扫一遍,复杂度q/k 。
重构次数不超过 。
复杂度O((q/k)n^2+qn+qk),当k=1000时可以通过该题。
#include<bits/stdc++.h>
#define N 1005
#define ll long long
using namespace std;
ll q[N][N],v[N][N],sum[N][N];
int n,Q,tot,a[N],b[N],c[N];
void add(int x,int y,int z){
for(int t=0;t<z;t++){
int i=x+t,j=y+t+1;
q[i][y]+=1;
q[i][j]-=1;
}
}
void rebuild(){
for(int i=1;i<=n;i++){
int t=0;
for(int j=1;j<=n;j++){
t+=q[i][j];
v[i][j]+=t;
sum[i][j]=sum[i][j-1]+v[i][j];
q[i][j]=0;
}
}
tot=0;
}
int main(){
scanf("%d%d",&n,&Q);
while(Q--){
int opt;
scanf("%d",&opt);
if(opt==1){
tot++;
scanf("%d%d%d",&a[tot],&b[tot],&c[tot]);
add(a[tot],b[tot],c[tot]);
if(tot==1000)rebuild();
}else{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
ll ans=0;
for(int t=0;t<z;t++){
int i=x+t,r=y+t;
ans+=sum[i][r]-sum[i][y-1];
}
for(int i=1;i<=tot;i++){
int aa=min(x+z-1,a[i]+c[i]-1);
int bb=max(y,b[i]);
int cc=max(x-y,a[i]-b[i]);
int len=aa-bb-cc+1;
if(x>aa||a[i]>aa)continue;//两个矩形上下无焦点
if(y+z-1<bb||b[i]+c[i]-1<bb)continue;//两个矩形左右无焦点
if(x+z-1-y<cc||a[i]+c[i]-1-b[i]<cc)continue;//斜率大于1则不可能
ans+=len<0 ? 0:len*(len+1)/2;
}
printf("%lld\n",ans);
}
}
return 0;
}