思路:看到题目我只知道,普通的暴力模拟是不行的,但是不知道用什么办法优化,然后看到网上的大佬们用了并查集恍然大悟;
用并查集维护每条船攻击后的根节点,最后输出查询位置的根节点就行,如果在期间存在该位置的根节点的下个位置的根节点也已经沉了,说明所有的船都已经沉了,退出循环;
代码如下:
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include<string>
#include <cmath>
#include<stack>
using namespace std;
int a[100050], b[100050];
int f[100050];
int find(int x)
{
if (x == f[x])//说明已经是根节点了
return x;
else
return f[x] = find(f[x]);//如果不是根节点,则找它的父节点
}
int main()
{
int n, m;
while (~scanf("%d%d",&n,&m))
{
for (int i = 1; i <=n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
{
scanf("%d", &b[i]);
f[i] = i;
}
int flag = 0;
f[n+1] = 1;//*****************这步很重要!!!!******************把最后一条船后面的位置设置成1,说明这个位置指向对方的第一条船
//用来满足条件中的:如果不存在,则攻击最远离 i 并且< i 没有死亡的敌方战舰。
while(m--)
{
if (flag)
break;
for (int i = 1; i <= n; i++)
{
int t = find(i);
a[t] -= b[i];
if (a[t] <= 0)//如果i位上的根节点已经沉没了
{
int tt = find(t + 1);//找根节点的下个节点的根节点
if (a[tt] <= 0)//说明该点的根节点已经沉了,说明战斗已经胜利
{
flag = 1;
break;
}
else
{
f[t] = tt;//如果没有沉,说明战斗还没有结束,f[t]指向根节点
}
}
}
}
int c;
int i;
scanf("%d", &c);
while (c--)
{
scanf("%d", &i);
if (flag)
printf("win\n");
else
printf("%d\n", find(i));
}
}
return 0;
}