[蓝桥杯][2018年第九届真题]三体攻击

个人题解链接,蓝桥杯历届试题,正在更新中~

三体攻击

题目描述
三体人将对地球发起攻击。为了抵御攻击,地球人派出了 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
思路
显然的二分+显然的三维差分+前缀和。差分的记法,相邻的异号,前缀和的记法该点加上和自己相距为奇数的点减去为偶数的点。

但是这题在C语言网上交会被卡常。(机子慢
优化:数据用一维数组来存,做前缀和还有输入的时侯都不要调用三维坐标转一维坐标函数,直接手动减。然后就过了。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double Pi = acos(-1);
namespace {
  template <typename T> inline void read(T &x) {
    x = 0; T f = 1;char s = getchar();
    for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
    for(;  isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
    x *= f;
  }
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i <  (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define _srep(n,m,i)for (register int i = (n); i >= (m); i--)
#define _sfor(n,m,i)for (register int i = (n); i >  (m); i--)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
const int N = 2e6+5;
struct node {
  int la, ra, lb, rb, lc, rc;
  LL  h;
  void get() {
    read(la); read(ra);read(lb); read(rb);read(lc); read(rc); read(h);
  }
}op[N];
LL a[N], b[N];
int A, B, C, m;
inline int get(int i, int j, int k) {
  return ((i-1) * B + j - 1) * C + k;
}
void ready(int n) {
  b[get(op[n].la, op[n].lb, op[n].lc)] += op[n].h;
  b[get(op[n].ra+1, op[n].lb, op[n].lc)] -= op[n].h;
  b[get(op[n].la, op[n].rb+1, op[n].lc)] -= op[n].h;
  b[get(op[n].la, op[n].lb, op[n].rc+1)] -= op[n].h;
  
  b[get(op[n].ra+1, op[n].rb+1, op[n].rc+1)] -= op[n].h;
  b[get(op[n].la, op[n].rb+1, op[n].rc+1)] += op[n].h;
  b[get(op[n].ra+1, op[n].lb, op[n].rc+1)] += op[n].h;
  b[get(op[n].ra+1, op[n].rb+1, op[n].lc)] += op[n].h;
}
bool judge(int m) {
  memset(b, 0, sizeof b);
  _rep(1, m, i) ready(i);
  _rep(1, A*B*C, l) {
    b[l] -= b[l-B*C-C];//b[get(i-1, j-1, k)];
    b[l] -= b[l-B*C-1];//b[get(i-1, j, k-1)];
    b[l] -= b[l-C-1]; //b[get(i, j-1, k-1)];
    
    b[l] += b[l-B*C];//b[get(i-1, j, k)];
    b[l] += b[l-C];//b[get(i, j-1, k)];
    b[l] += b[l-1];//b[get(i, j, k-1)];
    b[l] += b[l-B*C-C-1];//b[get(i-1, j-1, k-1)];
    if(b[l] > a[l]) return 1;
  }
  return 0;
}
int main() {
  read(A); read(B); read(C); read(m);
  _rep(1, A*B*C, i) read(a[i]);
  _rep(1, m, i) op[i].get();
  int l = 1, r = m, ans;
  judge(1);
  while(l <= r) {
    int mid = l + r >> 1;
    if(judge(mid)) {
      ans = mid; r = mid-1;
    } else l = mid + 1;
  }
  cout << ans;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值