题解:P17068 [ICPC 2017 Shenyang R] Defense of the Ancients
lailai0916 · · 题解
题意简述
双方各有若干单位,每个单位有生命值与攻击力。 存活单位会集火一个敌人,击杀后再选择下一个目标。 双方都采用最优击杀顺序,求最终胜负。
解题思路
先固定双方的击杀顺序。
对单位队累计受到的伤害量记为
在游戏尚未结束时,双方造成伤害的速度分别等于当前总攻击力,因此:
考虑两个势函数:
对时间求导可得:
又有
对于某一支队伍,设敌方依次击杀其第
可以把
每支队伍决定的是对方的击杀顺序。
为了尽快消灭对方,应让对方的
先击杀
前者减去后者等于
由相邻交换法,按
代码把这个顺序反转,按
攻击力总和能装入 64 位无符号整数,
但
参考代码
#include <bits/stdc++.h>
using namespace std;
using ull=unsigned long long;
using u128=__uint128_t;
const int N=100005;
struct unit
{
ull h,a;
};
unit a[N],b[N];
bool cmp(const unit &x,const unit &y)
{
return (u128)x.h*y.a>(u128)y.h*x.a;
}
u128 calc(unit a[],int n)
{
sort(a+1,a+n+1,cmp);
ull sum=0;
u128 res=0;
for(int i=1;i<=n;i++)
{
sum+=a[i].a;
res+=(u128)a[i].h*sum;
}
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin>>T;
while(T--)
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i].h;
for(int i=1;i<=n;i++)cin>>a[i].a;
for(int i=1;i<=m;i++)cin>>b[i].h;
for(int i=1;i<=m;i++)cin>>b[i].a;
u128 x=calc(a,n);
u128 y=calc(b,m);
if(x>y)cout<<"Units win";
else if(x<y)cout<<"Towers win";
else cout<<"Tie";
cout<<'\n';
}
return 0;
}