BZOJ3840: ZCC Loves COT

正解十分鬼畜…对标记的标记打标记….

由于我匮乏的空间想象能力,我果断打了 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值