Educational Codeforces Round 151 (Rated for Div. 2)

A. Forbidden Integer

贪心的分情况讨论:x没被禁,全1,x被禁,分情况讨论:

如果k<=1,无解。 k=2时奇数,无解。 k>2时,有解。

void solve(){
    int n, k, x; cin >> n >> k >> x;
    if (x != 1){
        vi a(n, 1);print(yes); print(len(a));print(a);return;
    }
    else{
        if (k <= 1) {print(no); return;}
        else if (k == 2 && n & 1){print(no); return;}
        else {  print(yes);
            vi a;
            while (n > 3) {a.pb(2); n-= 2;}
            a.pb(n == 2 ? 2 : 3);
            print(len(a));
            print(a);
        }
    }
}
 

B. Come Together

二维空间中三个点ABC,求BC到A的最短路径中的最长公共距离。问题等价于:求A到BC的路径中最长公共距离。

当B和C有公共距离时,A一定是满足这个条件:A在BC上或者下方,A在BC左或者右方,直接计算即可。

void solve(){
    ll dis = 0;
    pi a, b, c; cin >> a.first >> a.second >> b.first >>  b.second >>c.first >>c.second;
    if (a.first >= max(b.first, c.first)) {dis += a.first - max(b.first, c.first);}
    else if (a.first <= min(b.first, c.first)) {dis += min(b.first, c.first) - a.first;}
    //print(dis);
    if (a.second >= max(b.second, c.second)) {dis += a.second - max(b.second, c.second); }
    else if (a.second <= min(b.second, c.second)) {dis += min(b.second, c.second) - a.second;}
    print(dis + 1);
}
 

最后dis+1是考虑了在a点汇合时的一个公共坐标

C. Strong Password

枚举字符串的时间复杂度是O(n * pow(m, 10)),必TLE。

于是问题转换为构造S中不出现的子串。

答案字符串的长度为m,对于0~m-1位置的字符,贪心地枚举每个位置上的字符的最远匹配距离。这个策略可以证明一定是最优解。

void solve(){
    string s; cin >> s;
    int m; cin >> m;
    string t1, t2;cin >>t1 >> t2;
    int rb = 0;
    lfor (i, 0, m - 1){
        int r = 0;
        if(t1[i] > t2[i]) swap(t1[i], t2[i]);
        while (t1[i] <= t2[i]){
            int t = s.find(t1[i], rb);
            if(t==-1){print(yes); return;}
            t ++;
            r = max(r, t);
            t1[i] ++;
        }
        rb = max(rb, r);
    }
    print(no);
}

D. Rating System

在数组求前缀和的过程中找到一个k值,当前缀和在做减法运算时,可以让前缀和不低于k。求前缀和最大的情况下的k值。

贪心策略:可以发现为了让最终前缀和最大,需要消除掉在计算过程中对前缀和影响最大的负数。于是问题转化为,贪心查找数组中连续区间的最小值(值是负数),然后记录这个区间前面的前缀和,就是答案。

void solve(){
    int n; cin >> n;
    vi a(n); liter(x, a) cin >> x;
    ll minn = 2e9;
    ll curmin = 0;
    ll sum = 0;
    ll ans = 0;
    ll presum = 0;
    lfor (i, 0, n - 1){
        curmin += a[i];
        if (cmin(minn, curmin)){        //全局最小值小于当前局部连续区间最小值
            ans = presum;
        }
        sum += a[i];
        if (cmin(curmin, 0ll)){         //当前局部连续区间最小值大于0,舍弃之前的区间,并记录当前的前缀和
            presum = sum;
        }

    }
    print(ans);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值