一維差分/二維差分/ 三維差分 (通俗易懂)
阿新 • • 發佈:2022-04-02
一維差分:
- 比較容易理解, 就是每一個單位元素和前面一個元素的差值,通過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