P8666 [蓝桥杯 2018 省 A] 三体攻击 题解
DreamLand_zcb · · 题解
简要题意
有
思路
先定义结构体储存每轮攻击信息:
struct node{
int la, ra, lb, rb, lc, rc, h;
}t[N];
刚看到这道题的时候立马就想到了建一个三维的差分数组,每次进攻就对差分数组操作一次然后再判断是否有战舰爆炸,可是很容易发现这个思路会超时。
再仔细想一想可以发现,这
int l=1, r=m;
while(l < r)
{
int mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid+1;
}
cout << l;
问题又来了, check(mid) 怎么写?思考一下对于二分每个 r=mid ;但如果没有战舰爆炸,说明第 l=mid+1 。于是 check(mid) 的框架就有了:
bool check(int mid)
{
mem(b, 0);
for (int i=1; i<=mid; i++)
{
//三维差分
}
for(int i=1;i<=A;i++)
{
for(int j=1;j<=B;j++)
{
for(int k=1;k<=C;k++)
{
//构造出所有受到伤害的战舰的数组
if(/*每个战舰收到的伤害大于该战舰生命值*/) return 1;
}
}
}
return 0;
}
现在,check(mid) 写完了,最后一步就是写差分了,建议使用一维数组储存,三维数组会 RE ,而且写起来还很麻烦。使用一维数组的时候,就可以用题目中做给的公式储存了:第 为了方便,我们把这个公式定义成一个函数:
int get_xyz(int x, int y, int z)
{
return ((x-1)*B+(y-1))*C+(z-1)+1;
}
建立差分的代码也有了:
for (int i=1; i<=mid; i++)
{
b[get_xyz(t[i].la, t[i].lb, t[i].lc)]+=t[i].h;
b[get_xyz(t[i].ra+1, t[i].lb, t[i].lc)]-=t[i].h;
b[get_xyz(t[i].la, t[i].rb+1, t[i].lc)]-=t[i].h;
b[get_xyz(t[i].la, t[i].lb, t[i].rc+1)]-=t[i].h;
b[get_xyz(t[i].ra+1, t[i].rb+1, t[i].lc)]+=t[i].h;
b[get_xyz(t[i].ra+1, t[i].lb, t[i].rc+1)]+=t[i].h;
b[get_xyz(t[i].la, t[i].rb+1, t[i].rc+1)]+=t[i].h;
b[get_xyz(t[i].ra+1, t[i].rb+1, t[i].rc+1)]-=t[i].h;
//其实类似于三维数组的差分,本质就是容斥原理
//所以只要把get_xyz(i, j, k)想成三维数组的a[i][j][k]就好了
}
判断的代码也可以补全了:
for(int i=1;i<=A;i++)
{
for(int j=1;j<=B;j++)
{
for(int k=1;k<=C;k++)
{
b[get_xyz(i, j, k)]+=
b[get_xyz(i-1, j, k)]+
b[get_xyz(i, j-1, k)]+
b[get_xyz(i, j, k-1)]-
b[get_xyz(i-1, j-1, k)]-
b[get_xyz(i-1, j, k-1)]-
b[get_xyz(i, j-1, k-1)]+
b[get_xyz(i-1, j-1, k-1)];
if(b[get_xyz(i, j, k)] > d[get_xyz(i, j, k)]) return 1;
}
}
}
return 0;
完整代码
#include <bits/stdc++.h>
#define ll long long
#define mem(a, m) memset(a, m, sizeof(a));
using namespace std;
const int N=1e7+5;
int A, B, C, m;
int d[N];//血量
int b[N];//差分
struct node{
int la, ra, lb, rb, lc, rc, h;
}t[N];
int get_xyz(int x, int y, int z)
{
return ((x-1)*B+(y-1))*C+(z-1)+1;
}
bool check(int mid)
{
mem(b, 0);
for (int i=1; i<=mid; i++)
{
b[get_xyz(t[i].la, t[i].lb, t[i].lc)]+=t[i].h;
b[get_xyz(t[i].ra+1, t[i].lb, t[i].lc)]-=t[i].h;
b[get_xyz(t[i].la, t[i].rb+1, t[i].lc)]-=t[i].h;
b[get_xyz(t[i].la, t[i].lb, t[i].rc+1)]-=t[i].h;
b[get_xyz(t[i].ra+1, t[i].rb+1, t[i].lc)]+=t[i].h;
b[get_xyz(t[i].ra+1, t[i].lb, t[i].rc+1)]+=t[i].h;
b[get_xyz(t[i].la, t[i].rb+1, t[i].rc+1)]+=t[i].h;
b[get_xyz(t[i].ra+1, t[i].rb+1, t[i].rc+1)]-=t[i].h;
}
for(int i=1;i<=A;i++)
{
for(int j=1;j<=B;j++)
{
for(int k=1;k<=C;k++)
{
b[get_xyz(i, j, k)]+=
b[get_xyz(i-1, j, k)]+
b[get_xyz(i, j-1, k)]+
b[get_xyz(i, j, k-1)]-
b[get_xyz(i-1, j-1, k)]-
b[get_xyz(i-1, j, k-1)]-
b[get_xyz(i, j-1, k-1)]+
b[get_xyz(i-1, j-1, k-1)];
if(b[get_xyz(i, j, k)] > d[get_xyz(i, j, k)]) return 1;
}
}
}
return 0;
}
int main()
{
ios::sync_with_stdio(false);
cin >> A >> B >> C >> m;
for(int i=1;i<=A;i++)
{
for(int j=1;j<=B;j++)
{
for(int k=1;k<=C;k++)
{
cin >> d[get_xyz(i, j, k)];
}
}
}
for(int i=1;i<=m;i++)
{
cin >> t[i].la >> t[i].ra >> t[i].lb >> t[i].rb >> t[i].lc >> t[i].rc >> t[i].h;
}
int l=1, r=m;
while(l < r)
{
int mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid+1;
}
cout << l;
return 0;
}