正解十分鬼畜…对标记的标记打标记….
由于我匮乏的空间想象能力,我果断打了 O(n3+nm+nq) 的二维情况,然后卡过去了233
考虑一维的情况,就是对l~r区间+1,差分后在l,r+1分别打标记,所有操作完扫一次
问题拓展到二维时类似,观察对每一维打的标记,
+1,-1显然可以分开维护,+1标记是一列下去的,-1标记是沿斜线下去的,所以我们可以这样
用紫色的标记给+1标记打标记,红色的标记给-1标记打标记,所有操作完后扫一遍二维标记复原出一维标记,再扫一遍一维标记复原出原矩阵
于是我操作的时候枚举每一层去处理了二维的情况…
当问题拓展到三维….这个空间四面体的情况会变得很鬼畜….我没有去研究(没有能力qwq
想看正解戳这
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
inline void read(int &x)
{
char c; while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
const int maxn = 128;
int n,m,q;
int flag[maxn][maxn][maxn],flagc[maxn][maxn][maxn],flagk[maxn][maxn][maxn];
ll sum[maxn][maxn],sumc[maxn][maxn][maxn],sumk[maxn][maxn][maxn];
int main()
{
read(n); read(m); read(q);
for(int i=1;i<=m;i++)
{
int x,y,z,ai; read(x); read(y); read(z); read(ai);
for(int j=1;j<=ai;j++)
{
//x+j-1,y~y+j-1,z~z+j-1
int dep=x+j-1,d=y,u=y+j-1,l=z,r=z+j-1;
flagc[dep][d][l]++,flagc[dep][u+1][l]--;
flagk[dep][d][l+1]--,flagk[dep][u+1][r+2]++;
}
}
for(int i=1;i<=n;i++)
{
//i,1~i,1~i
for(int z=1;z<=i;z++)
{
int tmp=0;
for(int y=z;y<=i;y++)
{
tmp+=flagc[i][y][z];
flag[i][y][z]+=tmp;
}
}
for(int y=1;y<=i;y++)
{
int tmp=0;
for(int z=1;y+z-1<=i;z++)
{
tmp+=flagk[i][y+z-1][z];
flag[i][y+z-1][z]+=tmp;
}
}
for(int y=1;y<=i;y++)
{
int tmp=0;
for(int z=1;z<=y;z++)
{
tmp+=flag[i][y][z];
sum[y][z]=sum[y][z-1]+tmp;
}
}
for(int z=1;z<=i;z++) for(int y=z;y<=i;y++)
sumc[i][y][z]=sumc[i][y-1][z]+sum[y][z];
for(int y=1;y<=i;y++) for(int z=1;y+z-1<=i;z++)
sumk[i][y+z-1][z]=sumk[i][y+z-2][z-1]+sum[y+z-1][z];
}
while(q--)
{
int x,y,z,ai; read(x); read(y); read(z); read(ai);
ll re=0;
for(int j=1;j<=ai;j++)
{
//x+j-1,y~y+j-1,z~z+j-1
int dep=x+j-1,d=y,u=y+j-1,l=z,r=z+j-1;
re+=(sumk[dep][u][r]-sumk[dep][d-1][l-1])-(sumc[dep][u][l-1]-sumc[dep][d-1][l-1]);
}
printf("%lld\n",re);
}
return 0;
}