时间限制: 1 Sec 内存限制: 128 MB
提交: 134 解决: 30
[状态] [讨论版] [提交] [命题人:admin]
题目描述
为了保护科普卢星区的和平,大主教阿塔尼斯每时每刻都在指挥部队抗击肆虐的虫群。最近,阿塔尼斯把目光投向了又一颗布满虫群的星球。在这次行动中,阿塔尼斯计划使用狂热者铲除星球上的虫群威胁。
狂热者是星灵的基本近战兵种,每个狂热者有一个攻击力 atk 和一个攻击范围 r。在狂热者发动攻击时,他会冲向距离最近的异虫,在这只异虫处释放 3 次威力强大的旋风斩。若有多只距离最近的异虫,他会选择最早出现的那只。若当前没有存活的异虫,那么这只狂热者会在原地释放旋风斩。每次旋风斩会对所有与攻击者距离小于等于 r 的异虫进行攻击,对每只异虫造成 atk 的伤害(生命值减少 atk)。
当然,这些异虫也是不好惹的。每只异虫具有初始生命值 h,当生命值小于等于 0 时,该异虫将会死亡(并离开战场)。但是,在一次攻击中,若一只异虫受到 3 次旋风斩后仍未死亡,那么它将会对进攻的狂热者进行反击,使这个狂热者不得不离开战场。
在整个战役中,按照时间顺序依次发生了 n 个事件,事件有以下两种:
- 异虫出现。一只初始生命值为 h 的异虫单位出现在 (x,y)坐标。
- 折跃狂热者。一个狂热者被折跃到了 (x,y) 坐标,冲向距离最近的异虫(若存在)并发动 3 次旋风斩。若此后该狂热者没有受到反击,那么他将会一直留在战场,但是不会继续进行攻击。
你作为阿塔尼斯的副官,想知道战场的最终情况:每个狂热者是否离开了战场,以及每只异虫是否死亡。
输入
第一行包含一个整数 n (1≤n≤2×103),代表事件的数量。
接下来 n 行,每行给出一种事件,格式为以下两种之一:
1 x y h,代表一个生命值为 h 的异虫出现在了坐标 (x,y)。
2 x y atk r,代表一个攻击力为 atk,攻击半径为 r 的狂热者被折跃到了坐标 (x,y),并立即进行攻击。
上述所有的x,y,r 均为整数,满足 0≤∣x∣,∣y∣,r≤108;所有的 atk,h 均为整数,满足 1≤atk,h≤108。
输出
输出 n 行,第 i 行表示第 i 个事件中出现的异虫或狂热者最终是否留在战场。Yes 表示异虫未死亡或狂热者未离开战场,No 表示异虫死亡或狂热者离开战场,大小写不敏感。
样例输入 Copy
5 1 0 0 4 1 0 1 8 2 1 0 1 1 2 1 0 1 1 2 1 0 1 1
样例输出 Copy
No No No No Yes
提示
在样例中,发生了如下事件:
- 事件 1 中,在 (0,0)处出现了一只异虫,其生命值为 4。
- 事件 2 中,在 (0,1)处新出现了一只异虫,其生命值为 8。
- 事件 3 中,在 (1,0) 处折跃一只攻击力为 1,攻击半径为 1 的狂热者,他移动到坐标 (0,0) 后,发动 3 次旋风斩。异虫 1,2 分别剩余生命值 1,5,随后狂热者受到反击离开战场。
- 事件 4 中,在 (1,0) 处折跃一只攻击力为 1,攻击半径为 1 的狂热者,他移动到坐标 (0,0) 后,发动 3 次旋风斩。异虫 1 死亡,异虫 2 剩余生命值 2,随后狂热者受到反击离开战场。
- 事件 5 中,在 (1,0) 处折跃一只攻击力为 1,攻击半径为 1 的狂热者,他移动到坐标 (0,1) 后,发动 3 次旋风斩。异虫 2 死亡,狂热者留在战场。
因而,最终所有异虫死亡,只有狂热者 5 留在战场。
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<map>
#include<set>
using namespace std;
const long long inf=1e17+10;
const int maxn=10010;
struct bug{
int id;
int x,y;
int h;
bug(){}
bug(int _id,int _x,int _y,int _h){
id=_id;
x=_x;
y=_y;
h=_h;
}
};
int n;
int k,x,y;
int atk,r,h;
vector<bug> bugs;
vector<bool> ans;
bool getPoint(int &newX,int &newY){
bool judge=false;
bug ans;
long long Min=-1;
// x y atk r
int len = bugs.size();
if(len==0) {
return false;
}
for(int i=0;i<len;i++){
bug tmp = bugs[i];
if(tmp.h<=0) continue;
judge = true;
long long distance = (long long) ( (long long) (x-tmp.x) * (x-tmp.x) + (long long) (y-tmp.y) * (y-tmp.y) );
// cout<<"distance "<<distance<<endl;
if(Min==-1) {
Min=distance;
ans = tmp;
}
else if(distance < Min){
Min = distance;
ans = tmp;
}
}
if(judge==false) return false;
// cout<<"Min "<<Min<<endl;
newX = ans.x;
newY = ans.y;
// cout<<"newX "<<newX<<" newY "<<newY<<endl;
return true;
}
bool attack(int newX,int newY){
// 发动进攻可能 会导致 此次的 狂热者 死亡, 或者 之前出现在场地的 虫子 死亡
// 虫子可能 死 多个
// newX newY atk r
bool flag = true;
int len = bugs.size();
for(int i=0;i<len;i++){
bug tmp = bugs[i];
if(tmp.h<=0) continue;
long long distance = (long long) ( (long long) (newX-tmp.x) * (newX-tmp.x) + (long long) (newY-tmp.y) * (newY-tmp.y) );
// 在攻击范围内的 bug 将受到 旋风斩的 冲击
if(distance <= ( (long long) r) *(long long) r){
tmp.h-=3*atk;
if(tmp.h<=0){
bugs[i].h-=3*atk;
}
else{
flag = false;
bugs[i].h-=3*atk;
}
}
}
return flag;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n;
ans.resize(n);
for(int i=0;i<n;i++){
cin>>k>>x>>y;
if(k==1){
cin>>h;
bugs.push_back( bug(i,x,y,h) );
}else if(k==2){
cin>>atk>>r;
// 得到落地点
int newX=x,newY=y;
bool flag1 = getPoint(newX,newY);
// cout<<newX<<" "<<newY<<endl;//----------------------
if(flag1==false){
// 说明没有虫子 原地放技能,且活到最后
ans[i]=true;
// cout<<true<<"dsafasdf";//---------------------------
}
//进行攻击
else{
// newX,newY
bool flag = attack(newX,newY);
// 有虫子 进行攻击,将攻击范围内的所有的虫子都 杀死,自己到最后也活着
// 没杀死攻击范围内的所有的虫子 自己死
ans[i]=flag;
// cout<<flag;//-------------------------
}
}
}
// 判断 是 虫子的事件 中 虫子 是死是活
int len = bugs.size();
for(int i=0;i<len;i++){
bug tmp = bugs[i];
if(tmp.h<=0){
ans[ tmp.id ] = false;
// cout<<false<<endl;
}else{
ans[ tmp.id ] = true;
// cout<<true<<endl;
}
}
len = ans.size();
for(int i=0;i<len;i++){
if(ans[i]) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}