'''
標題:三體攻擊
【題目描述】
三體人將對地球發起攻擊。爲了抵禦攻擊,地球人派出了 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消耗 < 3000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多餘內容。
'''# 思路:# 1)範圍攻擊用差分記錄,這樣每次攻擊只需花O(1)的時間來記錄# 2)二分攻擊次數,攻破了,就在下半區二分回覆血量,沒攻破就在上半區再二分繼續攻擊 O(logm)# 3)每次檢查是否攻破,求差分前綴和求最終血量,再遍歷ABC個格子,看是否有血量小於0來判斷 O(ABC)from copy import copy
a, b, c =0,0,0defgetX(i, j, k):'''
:param i:
:param j:
:param k:
:return: 轉爲1維索引
'''return((i -1)* b + j -1)* c + k
defadd(cc, i, j, k, h):'''
修改ijk座標的差分數組的值
:param cc:
:param i:
:param j:
:param k:
:param h:
:return:
'''if i < a and j < b and k < c:
cc[getX(i, j, k)]+= h
defop(cc, atk, f):'''
:param cc: 差分數組
:param atk: 元組,數據是一次攻擊的相關參數
:param f: 1或者-1,代表攻擊還是回覆血量
:return: void
'''
la, ra, lb, rb, lc, rc, h = atk
h = h * f
add(cc, la, lb, lc, h)
add(cc, la, rb +1, lc,-h)
add(cc, la, lb, rc +1,-h)
add(cc, la, rb +1, rc +1, h)
add(cc, ra +1, lb, lc,-h)
add(cc, ra +1, rb +1, lc, h)
add(cc, ra +1, lb, rc +1, h)
add(cc, ra +1, rb +1, rc +1,-h)defcheck(cc, d):'''
三個維度累加,得差分數組的前綴和,就能得到每個點上的當前血量的變化量
:param cc:
:param d:
:return:
'''# 差分數組的前綴和,來自差分數組的複製
_sum = copy(cc)for i inrange(2, a):for j inrange(1, b):for k inrange(1, c):
_sum[getX(i, j, k)]+= _sum[getX(i -1, j, k)]for i inrange(1, a):for j inrange(2, b):for k inrange(1, c):
_sum[getX(i, j, k)]+= _sum[getX(i, j -1, k)]for i inrange(1, a):for j inrange(1, b):for k inrange(2, c):
_sum[getX(i, j, k)]+= _sum[getX(i, j, k -1)]# 遍歷每個點,檢查變化量是否大於原始血量for i inrange(1, a):for j inrange(1, b):for k inrange(1, c):
index = getX(i, j, k)if _sum[index]> d[index]:returnTruereturnFalseif __name__ =='__main__':# import sys## sys.stdin = open('/Users/zhengwei/data/in6.txt')
A, B, C, m =(int(x)for x ininput().strip().split(' '))
a, b, c = A +1, B +1, C +1
_d =[int(x)for x ininput().strip().split(' ')]# 原始血量數據# 統一爲三維情況
d =[0for _ inrange(a * b * c)]# 原始血量(爲了便於從1開始,增加長寬高,可用ijk定位)
index =0for i inrange(1, a):for j inrange(1, b):for k inrange(1, c):
d[getX(i, j, k)]= _d[index]
index +=1
cc =[0for _ inrange(a * b * c)]# 差分數組# 攻擊數據
atk =[tuple()]# 注意,下標從1開始,所以要佔位一個空的元組作爲0號元素for i inrange(m):
atk.append(tuple(int(x)for x ininput().strip().split(' ')))# print(atk[i])# 二分攻擊次數
l, r, lastMid =1, m,0while l < r:
mid =(l + r)>>1if lastMid < mid:# 上一次攻擊沒有攻破,繼續攻擊for i inrange(lastMid +1, mid +1):
op(cc, atk[i],1)# 修改差分數組elif lastMid > mid:# 上一次攻破了,恢復血量for i inrange(mid +1, lastMid +1):
op(cc, atk[i],-1)# 如果爆了,調整邊界if check(cc, d):
r = mid
else:
l = mid +1
lastMid = mid
print(r)
17 螺旋折線
提示:以右下角對角線上的點爲參照點(等差數列),測算給定的點到參照點要走的距離
'''
標題:螺旋折線
如圖p1.png所示的螺旋折線經過平面上所有整點恰好一次。
對於整點(X, Y),我們定義它到原點的距離dis(X, Y)是從原點到(X, Y)的螺旋折線段的長度。
例如dis(0, 1)=3, dis(-2, -1)=9
給出整點座標(X, Y),你能計算出dis(X, Y)嗎?
【輸入格式】
X和Y
對於40%的數據,-1000 <= X, Y <= 1000
對於70%的數據,-100000 <= X, Y <= 100000
對於100%的數據, -1000000000 <= X, Y <= 1000000000
【輸出格式】
輸出dis(X, Y)
【樣例輸入】
0 1
【樣例輸出】
3
資源約定:
峯值內存消耗(含虛擬機) < 256M
CPU消耗 < 1000ms
請嚴格按要求輸出,不要畫蛇添足地打印類似:“請您輸入...” 的多餘內容。
'''def_sum(a0, n, d):return(2* a0 +(n -1)* d)* n //2if __name__ =='__main__':# 以右下角對角線上的點爲參照點,測算給定的點到參照點要走的距離
X, Y =(int(i)for i ininput().strip().split(' '))
d, n =0,0# 距離和第幾圈if Y >0andabs(X)<= Y:
n = Y
d = Y - X +2* Y
elif X >0andabs(Y)<= X:
n = X
d = Y + X
elif Y <=0and Y -1<= X <=-Y:
n =-Y
d =-(-Y - X)elif X <0and X +1<= Y <=-X:
n =-X -1
d =-(Y - X -1-2* X -1)print(_sum(1,2* n,1)*2- d)