Educational Codeforces Round 166 (Rated for Div. 2)题解 by 吾骨封灯

 解题报告 -- 一份简陋的题解(考试临近,这是 CF网瘾少年最后的倔强了)

A 题, 犯罪啊,应该 3 min 内ac的,结果 WA 了一发,而且20min才交

加速AC 的知识: is_sored(st,ed, F-D)

或者

isalpha()用来判断一个字符是否为字母

isalnum用来判断一个字符是否为数字或者字母,也就是说判断一个字符是否属于a~ z||A~ Z||0~9。

isdigit() 用来检测一个字符是否是十进制数字0-9

islower()用来判断一个字符是否为小写字母,也就是是否属于a~z。

isupper()和islower相反,用来判断一个字符是否为大写字母。

bool  is_sorted(边界,边界,比较函数 =  default)

Auto  is_sorted_until(边界,边界,比较函数 =  default) //返回第一个不对的迭代器

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

const int N = 2e5 + 9;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
    int n; cin >> n;
    string ss; cin >> ss;
    ss = ' ' + ss;
    int key = 0;

    for(int i = 1;  i < ss.size(); i ++){
        if(isdigit(ss[i])  && key == 1){
            cout << "NO" << endl;
            return;
        }

        if(islower(ss[i]) && key == 0){
            key = 1;
        }else{
            if(ss[i-1] > ss[i]){
                cout << "NO" << endl;
                return;
            }
        }
    }
    cout << "YES" << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("in.txt", "rt", stdin), freopen("out.txt", "wt", stdout);
#endif
    int T = 1;
    cin >> T;
    while (T--)
        solve();
}

B 题, 一开始读假了,因为只有一个,我以为有好多个。只有一个就非常简单了,计算a-b的差值,并维护一个ans(拷贝成本),范围内 ans = 0,范围外,取最近。 (应该6min 内搞定的,结果花了20来分钟) -- (赛时写的shi山还在重测的时候寄了,下面的是赛后写的)

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

const int N = 2e5 + 9;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
    int n; cin >> n;
    vector<int> a(n),b(n+1);
    for(int &i:a) cin >> i;
    for(int &i:b) cin >> i;
    int ans = INF;
    for(int i = 0; i < n ; i ++ ){
        ans = min(ans, abs(a[i] - b[n]));
        ans = min(ans, abs(b[i] - b[n]));
        if(min(a[i],b[i]) <= b[n] && b[n] <= max(a[i],b[i])){
            ans = 0;
        }
    }

    for(int i = 0; i < n; i ++){
        ans += abs(a[i] - b[i]);
    }

    cout << ans + 1 << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("in.txt", "rt", stdin), freopen("out.txt", "wt", stdout);
#endif
    int T = 1;
    cin >> T;
    while (T--)
        solve();
}

C 题,赛场上没做出来,维护上面出问题,而且代码和思路出现了冲突还不自知,最后是代码写得太屎山了,已经到了不堪入目的程度了。

题解:也很简单,维护以下的变量

T -- 适合做程序员的人数

A -- 取n+1 个程序员的团队点数

p[i] -- 在找程序员满人情况的每个人是做哪个工作

B - 取 m + 1 个测试员团队点数

Q[i] -- 在找测试员满人情况情况的每个人是做怎么工作

如果 (T >= n) 那么这代表程序员会提前满员

这是就看被剔除的人是不是程序员

[p[i] == 1]是 -- 那么就取 A - a[i]  //  含义:少招募 1 个程序 -- n + 1 个程序的点数 - 当前程序员点数

不是 -- 那么就取 B - b[i] //  少招募 1 个测试 -- n + 1 个测试的点数 - 当前测试员点数

反过来 T < n

看被剔除的人是不是程序员

[q[i] == 1]不是 -- 那么就取 B - b[i] //  含义:少招募 1 个测试 -- n + 1 个测试的点数 - 当前测试员点数

是 -- 那么就取 A - a[i]  //  少招募 1 个程序 -- n + 1 个程序的点数 - 当前程序员点数

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

const int N = 2e5 + 9;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
    int n,m; cin >> n >> m;
    int len = n + m + 1;
    vector<int> a(len),b(len),p(len),q(len);
    for(int &i:a) cin >> i;
    for(int &i:b) cin >> i;

    int cnt1,cnt2,A,B,t;
    cnt1=cnt2=A=B=t = 0;

    for(int i = 0; i < len; i ++){
        t += a[i] > b[i];
        if(a[i] > b[i] && cnt1 <= n || m == i - cnt1){
            cnt1 ++;
            A += a[i];
            p[i] = 1;
        }else{
            A += b[i];
        }

        if(a[i] < b[i] && cnt2 <= m || n == i - cnt2){
            cnt2 ++;
            B += b[i];
            q[i] = 1; 
        }else{
            B += a[i];
        }
    }
    for(int i = 0; i < len ; i ++){
        cout << (t == n? (p[i]? A - a[i]:B - b[i]):(q[i]? B - b[i] : A - a[i]) ) << ' ' ;
    }
    cout << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("in.txt", "rt", stdin), freopen("out.txt", "wt", stdout);
#endif
    int T = 1;
    cin >> T;
    while (T--)
        solve();
}

D题 想了最久的一题,听群友说,要把问题抽象成折线图来思考

如果一个区间 反转合法

定义: 高度为未匹配 ’ ( ’的数量

条件1 --> 反转后区间外的未匹配括号数不变

那么只要反转的【左边界-1】和【右边界】的高度相等即可

条件2 --> 反转后区间内不能有不可能被匹配的情况(反转后高度为负数 / 有无法被匹配的 ’ ) ’ )

当前点高度 不能被 (高度-1)/2 的高度反转 (否则反转后高度为负数)

由此:每个点可以和前面所有合法点构成合法反转区间,在遍历某一个点时,累加前方同一高度合法点的数量,再把前方(高度-1)/2 的高度的点设置为非法(cnt[高度]清0)

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

const int N = 2e5 + 9;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
    string ss; cin >> ss;
    ss = ' ' + ss;

    vector<int> pre(ss.size()),cnt(ss.size());

    for(int i = 1; i < ss.size(); i ++){
        if(ss[i] == '(') pre[i] = pre[i-1] + 1;
        else pre[i] = pre[i-1] - 1;
    }

    int ans = 0;
    for(int i = 1; i < ss.size(); i ++){
        ans += cnt[pre[i]] ++;
        cnt[(pre[i] - 1) / 2] = 0;
    }

    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("in.txt", "rt", stdin), freopen("out.txt", "wt", stdout);
#endif
    int T = 1;
    cin >> T;
    while (T--)
        solve();
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值