Codeforces 733C Epidemic in Monstropolis

题目大意:有n只怪兽排成一列,体重大的可以吃掉相邻体重比他小的,吃掉后,体重便会相应地增加。给定初始怪兽和目标状态怪兽体重,问是否可能达成目标状态。可能输出“”YES“和步骤,不可能输出“NO”。

因为只能吃相邻的,所以目标状态肯定是由初始状态的连续子段和组成。那么遍历目标状态的各体重,判断能否由初始状态到达,即检查是否初始状态有连续子段的和等于该体重。若有连续子段等于该目标体重,那么是否一定能达到呢?可以发现,只要连续子段中各体重不全相等或者连续子段长度等于1,那么一定通过“一直向左吃之后一直向右吃”或者“一直向右吃之后一直向左吃”达到。

至于步骤的输出,遍历检查时记下各目标体重对应的连续子段的左右端点,在通过以上方法“吃”即可。

那么“吃“的起始点该怎么找呢?率先开吃的怪兽应该满足以下条件:1)它的体重是最重的,2)它的两边至少存在一个比它轻的。这两个条件保证了它这一次有的吃,而且吃完后还是最重的。

另外“NO”的判断,要注意吃完还有多余的怪兽,以及怪兽不够吃均是“NO”。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=500+15;
int sum[maxn];
int n, m, a[maxn], b[maxn];
int l[maxn], r[maxn];
bool can(int s,int t){
    int val=a[s];
    for(int i=s;i<=t;i++)
        if(a[i]!=val)
        return true;
    if(t==s) return true;
    return false;
}
void make(int cnt,int l,int r){
    int pos=l;
    for(int i=l;i<=r;i++)
    if(a[i]>a[pos])
        pos=i;
    else if(a[i]==a[pos]){
        if(pos==l)
            pos=i;
        else if(a[pos-1]==a[pos]&&a[pos]==a[pos])
            pos=i;
    }
//    printf("pos=%d\n",pos);

    if(pos==l||a[pos]==a[pos-1]){
        for(int i=pos;i<r;i++)
            printf("%d R\n",cnt+pos-l+1);
        for(int i=pos;i>l;i--)
            printf("%d L\n",cnt+i-l+1);
    }else{
        for(int i=pos;i>l;i--)
            printf("%d L\n",cnt+i-l+1);
        for(int i=pos;i<r;i++)
            printf("%d R\n",cnt+1);
    }
}
int main(){
    int no_ans=0;

    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
        scanf("%d",&b[i]);

    int i=1, j;
    for(j=1;j<=m;j++){
        int t=i;
        while(t<=n&&sum[t]-sum[i-1]<b[j])
            t++;
        if(t>n||sum[t]-sum[i-1]!=b[j]||!can(i,t)){
            no_ans=1;
            break;
        }
        if(j==m&&t!=n){
            no_ans=1;
            break;
        }
        l[j]=i, r[j]=t;
        i=t+1;
    }
    if(no_ans)
        puts("NO");
    else{
        puts("YES");
        for(j=1;j<=m;j++)
            make(j-1,l[j],r[j]);
    }


    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值