【codeforces 733 C】【模拟】C. Epidemic in Monstropolis【给你n个数,再给你k个数,问你a序列能否通过一定规则合并变成b序列】

传送门:http://codeforces.com/contest/733/problem/C



题意:给你n个数,a1,a2,a3,…an,再给你k个数b1,b2,b3,…bk,问你a序列能否通过合并变成b序列。合并的条件为只能相邻的数合并并且由大数向小数合并,然后通过新序列合并下去问你能不能达到b序列?能达到的话输出是如何合并的,不能的话输出NO。


思路:

1、我们可以把a序列分成k个连续的块,每个块的值的总和与b对应,对于每个块我们单独处理下,我们可以这个块的最大值开始向两边合并,切存在相邻的数小于它,然后一直合并下去就可以了
2、但这里有几个注意点,每个块不能合并的条件为这个块里所有元素都相等且块的长度不为1、b的总和和a的总和要相等。


PS:这题主要是看细节和码力


代码:

#include <bits/stdc++.h>
using  namespace  std;

#define ff first
#define ss second
#define mp make_pair
#define pb push_back
#define rep(i,k,n) for(int i=k;i<=n;i++)
#define rrep(i,k,n) for(int i=k;i>=n;i--)

template<class T> void read(T&num) {
    char CH; bool F=false;
    for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
    for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
    F && (num=-num);
}

int k, n;

int  main(){
  std::vector<int> a;
  read(n);
  rep(i, 1, n){
    int x; read(x);
    a.pb(x);
  }
  read(k);
  int it = 0;
  std::vector<pair<int, char> > ans;
  rep(i, 0, k - 1){
    set<int>h;
    int x;read(x);
    int v = 0, l = it, mx = -1;
    while(it < n && a[it] + v <= x){
      v += a[it]; //分块和
      mx = max(mx, a[it]); //分块的最大值
      h.insert(a[it]); //用于判断分块区域是否全等
      it++;   //当前指针
    }
    int r = it;
    //a序列变不了b序列或者分块的序列中值全相等都是不行的
    if(v != x || h.size() == 1 && l + 1 < r)return 0 * puts("NO");
    
    r--;
    rep(j, l + 1, r){
      
      if(max(a[j], a[j - 1]) == mx && min(a[j], a[j - 1]) != mx){//样例221
        if(a[j - 1] == mx){
          rep(k, j, r){
            ans.pb(mp(j - l + i, 'R'));//一直往右吃
          }
          rrep(k, j - 1, l + 1){
            ans.pb(mp(k - l + 1 + i, 'L'));//一直往左吃
          }
        }
        else{
          rrep(k, j, l + 1){
            ans.pb(mp(k - l + 1 + i, 'L'));//一直往左吃
          }
          rep(k, j, r - 1){
            ans.pb(mp(i + 1, 'R'));//一直往右吃
          }
        }
        break;
      }

    }
  }
  if(ans.size() != n - k)return 0 * puts("NO");
  puts("YES");
  for(auto x : ans)printf("%d %c\n", x.ff, x.ss);
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值