一维差分/二维差分/ 三维差分/ 树上差分

  一维差分:

  • 比较容易理解, 就是每一个单位元素和前面一个元素的差值,通过O(n) 时间复杂度 就可以把这个队列里面的值给弄出啦。
  • 用于解决很多次修改区间问题

  二维差分:

  • 同理可得,不过的单位元素的差值= val【I】[J] - val【I】[J-1] - VAL[I-1][J]+VAL[I-1][J-1] ;    建议自己简单画一个图来进行理解
  • O(n) 推导的时候  就 单位元素的差值+= val【I】[J-1] +VAL[I-1][J]-VAL[I-1][J-1] ; 
  • 在进行 矩形区间修改的时候就这样:(+2) 表示差分数组的值+2;

        为什么?

  • 考虑 3 个关键元素 :单位元素的差值+= val【I】[J-1] +VAL[I-1][J]-VAL[I-1][J-1] ;  就是这个等号右边的3个元素
  • 选择一个修改区间外的方块, 看他的 3个关键元素有没有在 修改区间内,
  • 如果在内,看他对上面这个等式的影响,然后 单位元素的差值 加上影响的相反数即可。

    三维差分:

  • 同理可得,单位元素的差值= val【I】[J] [z] - val【I】[J-1] [z] - VAL[I-1][J][z]+VAL[I-1][J-1] -val[i][j][Z-1]+VAL[I-1][J][Z-1]+VAL[[I][J-1][Z-1]-VAL[I-1][J-1][Z-1]; 
  • 求差分

    关键:  偶数个 1 的 符号一致, 奇数个1 符号和 前面的偶数符号相反。(通过 0,0,0的来确认符号)

const int  d[8][4] = {
         {0,0,0,1},
    {0,0,-1,-1},
    {0,-1,0,-1},
         {0,-1,-1,1},
    {-1,0,0,-1},
    {-1,0,-1,1},
    {-1,-1,0,1},
    {-1,-1,-1,-1}
};

二进制 8 , 前面是 代表xyz值,后面是加减的值的正负。
View Code

     区间修改: 和上面同理,不过1 变成 R+1, 

    for(ri i=1;i<=mid;i++)
    {
        b[get(p[i].la,p[i].lb,p[i].lc)]-=p[i].val;
        b[get(p[i].la,p[i].lb,p[i].rc+1)]+=p[i].val;
        b[get(p[i].la,p[i].rb+1,p[i].lc)]+=p[i].val;
        b[get(p[i].la,p[i].rb+1,p[i].rc+1)]-=p[i].val;
        b[get(p[i].ra+1,p[i].lb,p[i].lc)]+=p[i].val;
        b[get(p[i].ra+1,p[i].rb+1,p[i].lc)]-=p[i].val;
        b[get(p[i].ra+1,p[i].lb,p[i].rc+1)]-=p[i].val;
        b[get(p[i].ra+1,p[i].rb+1,p[i].rc+1)]+=p[i].val;
    }
View Code

 

例题:

试题 历届真题 三体攻击【第九届】【省赛】【A组】
     
资源限制
内存限制:256.0MB   C/C++时间限制:1.0s   Java时间限制:3.0s   Python时间限制:5.0s
问题描述
  三体人将对地球发起攻击。为了抵御攻击,地球人派出了 A × B × C 艘战舰,在太空中排成一个 A 层 B 行 C 列的立方体。其中,第 i 层第 j 行第 k 列的战舰(记为战舰 (i, j, k))的生命值为 d(i, j, k)。

  三体人将会对地球发起 m 轮“立方体攻击”,每次攻击会对一个小立方体中的所有战舰都造成相同的伤害。具体地,第 t 轮攻击用 7 个参数 lat, rat, lbt, rbt, lct, rct, ht 描述;
  所有满足 i ∈ [lat, rat],j ∈ [lbt, rbt],k ∈ [lct, rct] 的战舰 (i, j, k) 会受到 ht 的伤害。如果一个战舰累计受到的总伤害超过其防御力,那么这个战舰会爆炸。

  地球指挥官希望你能告诉他,第一艘爆炸的战舰是在哪一轮攻击后爆炸的。
输入格式
  从标准输入读入数据。

  第一行包括 4 个正整数 A, B, C, m;
  第二行包含 A × B × C 个整数,其中第 ((i − 1)×B + (j − 1)) × C + (k − 1)+1 个数为 d(i, j, k);
  第 3 到第 m + 2 行中,第 (t − 2) 行包含 7 个正整数 lat, rat, lbt, rbt, lct, rct, ht。
输出格式
  输出到标准输出。

  输出第一个爆炸的战舰是在哪一轮攻击后爆炸的。保证一定存在这样的战舰。
样例输入
2 2 2 3
1 1 1 1 1 1 1 1
1 2 1 2 1 1 1
1 1 1 2 1 2 1
1 1 1 1 1 1 2
样例输出
2
样例说明
  在第 2 轮攻击后,战舰 (1,1,1) 总共受到了 2 点伤害,超出其防御力导致爆炸。
数据约定
  对于 10% 的数据,B = C = 1;
  对于 20% 的数据,C = 1;
  对于 40% 的数据,A × B × C, m ≤ 10, 000;
  对于 70% 的数据,A, B, C ≤ 200;
  对于所有数据,A × B × C ≤ 10^6, m ≤ 10^6, 0 ≤ d(i, j, k), ht ≤ 10^9。


  资源约定:
  峰值内存消耗(含虚拟机) < 256M
  CPU消耗 < 2000ms


  请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

  注意:
  main函数需要返回0;
  只使用ANSI C/ANSI C++ 标准;
  不要调用依赖于编译环境或操作系统的特殊函数。
  所有依赖的函数必须明确地在源文件中 #include <xxx>
  不能通过工程设置而省略常用头文件。

  提交程序时,注意选择所期望的语言类型和编译器类型。
三体攻击【第九届】【省赛】【A组】

没有AC的代码,最后一个时间超时,qwq,全网找了很久每找到一个AC的,哎

思路,二分答案+差分

#include <bits/stdc++.h>
using namespace std;
#define ri register int
#define M 2000050


template <class G >  void read(G &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=f?-x:x;
    return ;
}
int A,B,C,m;
int get(int a,int b,int c)
{
    return (a*B+b)*C+c;
}
int xf[M],b[M];
const int  d[8][4] = {
    {0,0,0,1},
    {0,0,-1,-1},
    {0,-1,0,-1},
    {0,-1,-1,1},
    {-1,0,0,-1},
    {-1,0,-1,1},
    {-1,-1,0,1},
    {-1,-1,-1,-1}
};
int val[M];

struct dian{
    int la,ra,lb,rb,lc,rc,val;
}p[M];
int op[9];

void init()
{
        for(ri i=1;i<=A;i++)
        {
          for(ri j=1;j<=B;j++)
           {
            for(ri k=1;k<=C;k++)
            {
              b[get(i,j,k)]=xf[get(i,j,k)];
              val[get(i,j,k)]=0; //
            }
           }
        }
}
bool ck(int mid)
{
    init();
    for(ri i=1;i<=mid;i++)
    {
        b[get(p[i].la,p[i].lb,p[i].lc)]-=p[i].val;
        b[get(p[i].la,p[i].lb,p[i].rc+1)]+=p[i].val;
        b[get(p[i].la,p[i].rb+1,p[i].lc)]+=p[i].val;
        b[get(p[i].la,p[i].rb+1,p[i].rc+1)]-=p[i].val;
        b[get(p[i].ra+1,p[i].lb,p[i].lc)]+=p[i].val;
        b[get(p[i].ra+1,p[i].rb+1,p[i].lc)]-=p[i].val;
        b[get(p[i].ra+1,p[i].lb,p[i].rc+1)]-=p[i].val;
        b[get(p[i].ra+1,p[i].rb+1,p[i].rc+1)]+=p[i].val;
    }
    for(ri i=1;i<=A;i++)
    {
        for(ri j=1;j<=B;j++)
        {
            for(ri k=1;k<=C;k++)
            {
                int  tmp=0;
                for(ri cur=1;cur<=7;cur++) // zhu yi shu zhu d fan wei 
                {
                    int x=i+d[cur][0],y=j+d[cur][1],z=k+d[cur][2],h=d[cur][3];
                    tmp+=val[get(x,y,z)]*h;
                }
                val[get(i,j,k)]=b[get(i,j,k)]-tmp;
                if(val[get(i,j,k)]<0) 
                {
                    return 1;
                }
            }
        }
    }
    return 0;
    
    
}
int main(){
    
    read(A);read(B);read(C);read(m);
    for(ri i=1;i<=A;i++)
    {
        for(ri j=1;j<=B;j++)
        {
            for(ri k=1;k<=C;k++)
            {
                read(val[get(i,j,k)]);
            }
        }
    }
    
    for(ri i=1;i<=A;i++)
    {
        for(ri j=1;j<=B;j++)
        {
            for(ri k=1;k<=C;k++)
            {
                int  tmp=0;
                for(ri cur=0;cur<=7;cur++) // zhu yi shu zhu d fan wei 
                {
                    int x=i+d[cur][0],y=j+d[cur][1],z=k+d[cur][2],h=d[cur][3];
                    tmp+=val[get(x,y,z)]*h;
                }
               xf[get(i,j,k)]=tmp;
            }
        }
    }
    for(ri i=1;i<=m;i++)
    {
        read(op[1]);read(op[2]);read(op[3]);read(op[4]);read(op[5]);read(op[6]);read(op[7]);
        p[i].la=op[1];p[i].ra=op[2];p[i].lb=op[3];p[i].rb=op[4];p[i].lc=op[5];p[i].rc=op[6];p[i].val=op[7];
    }
    int l=1,r=m;
    
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(ck(mid)) r=mid;
        else l=mid+1;
    }
    printf("%d",r);
    return 0;

}
View Code

 

 

 

     

 

posted @ 2022-04-02 14:58  VxiaohuanV  阅读(564)  评论(0编辑  收藏  举报