Educational Codeforces Round 101(Div2) A~D

A题(贪心)Regular Bracket Sequence

题意:括号匹配问题,给定序列,含一个 ‘( ’ 一个 ’ )‘ 其他是问号,问号可以是左括号也可以是右括号,问能否构成 合法括号表达式

判断合法表达式,就是遇到左括号,进栈,遇到右括号,检验,出栈,最后最后栈是否空

关键在右括号

为了使右括号检验正确,贪心,前 s/2-1 个 ? 用 ( 代替 , 其他 ? 用 ) 代替

那么 只需要判断奇偶,第一个不是‘ ) ’ 最后一个不是 ’ ( ‘

#include <bits/stdc++.h>
using namespace std;
int main() {
    int t;
    cin>>t;
    while(t--){
        char a[200];
        cin>>a+1;
        int len=strlen(a)-1;
        if(len%2==0&&a[1]!=')'&&a[len]!='(')cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

B题(前缀和)Red and Blue

f(a)=a1+a2+……+ax=r1+r2+……+rm +b1+b2+……+bn (m,n可以为0)

分别求r数组和b数组前缀和最大的值(还要跟0比),相加得ans

#include<bits/stdc++.h>
#define rep(i,m,n)  for(int i=m;i<=n;i++)
using namespace std;
int a[200],b[200];
int main(){
    int t;
    cin>>t;
    while(t--){
        int n,m;
        cin>>n;
        int cnt1[200]={0};
        int cnt2[200]={0};
        int max1=0,max2=0;
        rep(i,1,n){
            scanf("%d",&a[i]);
            cnt1[i]=cnt1[i-1]+a[i];
            max1=max(max1,cnt1[i]);
        }
        cin>>m;
        rep(i,1,m){
            scanf("%d",&b[i]);
            cnt2[i]=cnt2[i-1]+b[i];
            max2=max(max2,cnt2[i]);
        }
        cout<<max1+max2<<endl;
    }
    return 0;
}

C题(DP)Building a Fence

状态:从左往右修,修到左边的第 i 块,这一块的底端的范围是[ l,r ] ,这一块底端选取区间内值,都存在着 左边总共i-1块的高度的一种方案 使得满足题目要求。

状态转移:i-1 ——> i [ li-1 , ri-1 ] ——> [max( hi , li-1 - (k -1)) , min( hi +k -1 , ri-1 +k -1 )]

(如果 li > ri 则说明无解)

最后 ln <= rn 且 ln == hn 则输出yes 否则no

#include <bits/stdc++.h>
#define ll long long
#define rep(i,m,n)   for(int i=m;i<=n;i++)
using namespace std;
const int maxn=3e5;
ll h[maxn];
int main() {
    int t;
    cin>>t;
    while(t--){
        int n,k,flag=1;
        cin>>n>>k;
        rep(i,1,n){
            scanf("%lld",&h[i]);
        }
        ll le=h[1],ri=h[1];
        rep(i,2,n){
            le=max(h[i],le-(k-1));
            ri=min(h[i]+k-1,ri+k-1);
            if(le>ri){flag=0;break;}
        }
        if(le!=h[n])flag=0;
        if(flag)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

D题 Ceil Divisions

题意:现有a数组ai =i ,即 1,2,3,,,,,n,一步操作就是任选x,y(注x!=y)ax=ax/ay 向上取整

目标是用不超过n+5步操作 使得a数组变成由 n-1个1, 1个2组成

解一:开方 递归

每一次选取( ⌈ \lceil ⌈ x \sqrt{x} x ​ ⌉ \rceil ⌉,x ] , 先对所有( ⌈ \lceil ⌈ x \sqrt{x} x ​ ⌉ \rceil ⌉,x )范围内的数m, 选 m,x进行一步操作,那么m变为1

然后 选x, ⌈ \lceil ⌈ x \sqrt{x} x ​ ⌉ \rceil ⌉ 进行一步操作,得到一个数。选这个数和 ⌈ \lceil ⌈ x \sqrt{x} x ​ ⌉ \rceil ⌉ 进行一步操作,得到1

这个过程中,操作次数=区间长度+1

如果n=232,操作次数=232 +3 ,故用以上方法,操作次数<=n+3

#include <bits/stdc++.h>
using namespace std;
#define rep(i,m,n)    for(int i=m;i<=n;i++)
#define fi first
#define se second
vector<pair<int,int>>vec;
int main() {
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--){
        vec.clear();
        int n;
        cin>>n;
        int st=ceil(sqrt(n));
        while(n>2){
            rep(i,st+1,n-1){
                vec.push_back({i,n});
            }
            vec.push_back({n,st});
            vec.push_back({n,st});
            n=st;
            st=ceil(sqrt(n));
        }
        cout<<vec.size()<<'\n';
        for(auto i:vec)cout<<i.first<<" "<<i.second<<'\n';
    }
    return 0;
}

解二:特殊值8

除了1,2,8,n 对其他每个值x 选x,n进行一步操作

然后 选n,8进行一步操作,循环,直至n变为1

然后 选8,2进行三步操作,8变为1

总的步数=n+5

选取16代替8也一样,总步数n+5

#include <bits/stdc++.h>

using namespace std;
#define rep(i, m, n)    for(int i=m;i<=n;i++)
#define fi first
#define se second
vector<pair<int, int>> vec;

int main() {
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--) {
        vec.clear();//清空
        int n;
        cin >> n;
        if (n > 8) {
            rep(i, 3, n - 1)
                if (i != 8)
                    vec.push_back({i, n});

            int tem = n;
            while (tem != 1) {
                vec.push_back({n, 8});
                tem = ceil(tem / 8.0);
            }

            tem = 8;
            while (tem != 1) {
                vec.push_back({8, 2});
                tem = ceil(tem / 2.0);
            }
        } else {
            rep(i, 3, n - 1) { vec.push_back({i, n}); }

            int tem = n;
            while (tem != 1) {
                vec.push_back({n, 2});
                tem = ceil(tem / 2.0);//注意要转化成double
            }
        }

        cout << vec.size() << '\n';
        for (auto i:vec)cout << i.first << " " << i.second << '\n';
    }
    return 0;
}
上一篇:Windows下安装MySQL5.7,安装时提示缺少【MSVCR120.dll】


下一篇:Leetcode189.旋转数组