Codeforces 1091F 题意 思路 程序
Good Bye 2018 F. New Year and the Mallard Expedition
一只鸭子想从数轴的左端走到右端
数轴上有三种环境:草原Grass,水Water,岩浆Lava
给定一个长度为(n)的字符串,表示自左向右的环境分布
再给定一个长度为(n)的数组,表示每种环境占的宽度
在草原上,鸭子只能走或者飞
在水上,鸭子只能游或者飞
在岩浆上,鸭子只能飞
鸭子走的速度为一米(5)秒,游的速度为一米(3)秒,飞的速度为一米(1)秒
同时,鸭子每走一米或者游一米可以积攒(1)个单位的体力,飞一米需要消耗(1)个单位的体力
鸭子不需要严格移动整数距离,比如宽度为(5)的草原可以走(2.5)米飞(2.5)米
鸭子也可以往回走或者游,用于积攒体力
初始时鸭子体力为(0),问从左端走到右端的最短时间,保证题目有解(即第一种环境一定不是岩浆)
限制
(1leq nleq 10^5)
(1leq l_ileq 10^{12})
思路
贪心模拟
假设目前我们需要经过一段长度为(len)的区域
方法有:
- 草原限定:走(frac {len} 2)米,飞(frac {len} 2)米,时间消耗(5*frac {len} 2+1*frac {len} 2=3*len)
- 水域限定:走(frac {len} 2)米,飞(frac {len} 2)米,时间消耗(3*frac {len} 2+1*frac {len} 2=2*len)
- 如果在这之前有水域是飞行经过的,那么可以将某一段从飞行改成游泳,每米将会多使用(3-1=2)秒的时间,但能量会从(-1)变成(+1),所以时间消耗(frac{(3-1)*len}{2}+1*len=2*len)
- 如果在这之前有草原是飞行经过的,那么可以将某一段从飞行改成走路,每米将会多使用(5-1=4)秒的时间,但能量会从(-1)变成(+1),所以时间消耗(frac{(5-1)*len}{2}+1*len=3*len)
- 如果之前有经过水域,那么可以让鸭子往回游积攒体力,时间消耗为(3*len+1*len=4*len)
- 如果之前有经过草原,那么可以让鸭子往回走积攒体力,时间消耗为(5*len+1*len=6*len)
所以对于本题,需要使用(isWater)与(isGrass)记录某个位置之前是否存在水域或者草原
使用(flyWater)与(flyGrass)记录某个位置之前在水域上飞行了多少米,在草原上飞行了多少米(也就是有多少米能用来更改)
所以可以进行模拟——
- 如果当前是草原,那么检查是否前面的水域中存在飞行经过的区域(因为将飞行改成游泳(2*len)比直接走并飞行(3*len)所花的时间少),再直接走并飞行
- 如果当前是水域,那么直接走并飞行((2*len)已经是最短时间了)
- 如果当前是岩浆,根据花费的时间排序((2lt3lt4lt6)),先判断并将某一段从飞行改成游泳,再判断并将某一段从飞行改成走路,再尝试让鸭子往回游积攒体力,最后尝试让鸭子往回走积攒体力
程序
(343ms/1000ms)
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#include<bits/stdc++.h>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define pb push_back
#define eb emplace_back
#define mst(a,b) memset(a,b,sizeof(a))
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const double angcst=PI/180.0;
const ll mod=998244353;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}
int n;
double len[100050];
char str[100050];
void solve()
{
cin>>n;
rep(i,1,n)
cin>>len[i];
cin>>str+1;
bool isWater=false,isGrass=false;
double ans=0;
double flyWater=0,flyGrass=0;
double tmp;
rep(i,1,n)
{
if(str[i]=='G')
{
if(flyWater)
{
tmp=min(len[i],flyWater*2);
flyWater-=tmp/2;
len[i]-=tmp;
flyGrass+=tmp;
ans+=tmp/2*(3-1)+tmp*1;
}
ans+=len[i]*3;
flyGrass+=len[i]/2;
isGrass=true;
}
else if(str[i]=='W')
{
ans+=len[i]*2;
flyWater+=len[i]/2;
isWater=true;
}
else
{
if(flyWater)
{
tmp=min(len[i],flyWater*2);
flyWater-=tmp/2;
len[i]-=tmp;
ans+=tmp/2*(3-1)+tmp*1;
}
if(flyGrass)
{
tmp=min(len[i],flyGrass*2);
flyGrass-=tmp/2;
len[i]-=tmp;
ans+=tmp/2*(5-1)+tmp*1;
}
if(isWater)
{
ans+=len[i]*(3+1);
len[i]=0;
}
if(isGrass)
{
ans+=len[i]*(5+1);
len[i]=0;
}
}
//cerr<<i<<' '<<ans<<'
';
}
cout<<(ll)ans<<'
';
}
int main()
{
closeSync;
//multiCase
{
solve();
}
return 0;
}