Educational Codeforces Round 111 (Rated for Div. 2) 题解(A-C)

Educational Codeforces Round 111 (Rated for Div. 2) 题解(A-C)

A. Find The Array

题目大意:

如果一个由 n n n个正整数组成的数组 a a a中每一位 a i ( 1 ≤ i ≤ n ) a_i(1\le i \le n) ai(1in)满足以下条件:

  • a i = 1 a_i=1 ai=1
  • a i − 1 a_i-1 ai1或者 a i − 2 a_i-2 ai2也存在于这个数组中

我们就称这个数组是漂亮的。

现在给出一个正整数 s s s,在保证漂亮数组和等于 s s s的情况下,数组的长度最小是多少。

解题思路:

很容易想到,在和固定的情况下,我们要使得数组中元素的个数最小,就得使得每个元素尽可能大,由于题目条件的限制,我们很容易想到 1 , 3 , 5 , 7 , . . . , 2 × n − 1 1,3,5,7,...,2\times n -1 1,3,5,7,...,2×n1这种构造方式。同时我们可以发现,如果按照这种方式构造数组之和超过了s,我们可以将部分数字减去 1 1 1 2 2 2,因为我们最多可以减去 2 × ( n − 1 ) 2\times(n-1) 2×(n1),所以但凡是用 n − 1 n-1 n1个数字之和无法大于等于 s s s的情况下,我们都可以用 n n n个数字完成构造。

代码:
#include<cstdio>
int n;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        int sum=0,res=0;
        for(int i=1;sum<n;i+=2){
            sum+=i;
            res++;
        }
        printf("%d\n",res);
    }
    return 0;
}

B. Maximum Cost Deletion

题目大意:

给出一个01字符串,每次可以删除一段相同的子串,假设每次删除的长度是 l l l,我们可以获得 a × l + b a\times l+b a×l+b的分数,问把字符串删成空串的情况下最高的分数是多少。

解题思路:

首先,我们可以发现,设字符串长度为 n n n,分数一定是 a × n + k × b a\times n+k\times b a×n+k×b,其中 k k k是执行操作的次数。

因为 − 100 ≤ b ≤ 100 -100\le b \le 100 100b100,所以我们可以根据 b b b的正负来选择贪心策略。

  • 如果 b > = 0 b>=0 b>=0,很显然我们需要尽可能多地执行操作,这时可以每次删除一个字符,一共删除 n n n次,所以答案就是 ( a + b ) ∗ n (a+b)*n (a+b)n
  • 如果b<0,很显然我们需要尽可能少地执行操作,这时我们可以每次删除一段连续的 0 0 0串或者 1 1 1串,最后再一次删除剩余的字符串,分别计算一下两种策略的次数取个min就行了。
代码:
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
string s;
int n,a,b;
int main()
{
    int T;
    cin>>T;
    while(T--){
        cin>>n>>a>>b;
        cin>>s;
        int res=a*n;
        if(b>=0)       res+=b*n;
        else{
            int num0=0,num1=0;
            for(int i=0;i<s.size();){
                if(s[i]=='0') num0++;
                else num1++;
                int j=i+1;
                while(j<s.size()&&s[j]==s[i]) j++;
                i=j;
            }
            res+=b*min(num0+1,num1+1);
        }
        cout<<res<<endl;
    }
    return 0;
}

C. Manhattan Subarrays

题目大意:

对于两个点 p = ( x p , y p ) p=(x_p,y_p) p=(xp,yp) q = ( x q , y q ) q=(x_q,y_q) q=(xq,yq),我们定义这两个点的曼哈顿距离 d ( p , q ) = ∣ x p − x q ∣ + ∣ y p + y q ∣ d(p,q)=|x_p-x_q|+|y_p+y_q| d(p,q)=xpxq+yp+yq

如果点 p , q , r p,q,r p,q,r满足 d ( p , r ) = d ( p , q ) + d ( q , r ) d(p,r)=d(p,q)+d(q,r) d(p,r)=d(p,q)+d(q,r),我们就称这三个点是一个坏三元组。

如果对于一个数组 b 1 , b 2 , . . . , b m b_1,b_2,...,b_m b1,b2,...,bm,如果我们无法选择三个不同的整数 i , j , k ( 1 ≤ i , j , k ≤ m ) i,j,k(1\le i,j,k\le m) i,j,k(1i,j,km)使得点 ( b i , i ) , ( b j , j ) , ( b k , k ) (b_i,i),(b_j,j),(b_k,k) (bi,i),(bj,j),(bk,k)构成坏三元组的话,我们就称这个数组是好的。

现在给出一个数组 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an,请计算 a a a中有多少个子数组是好的。

如果某个数组的长度小于 3 3 3,那么这个数组也是好数组。

解题思路:

我们可以发现,如果对于某三元组 ( i , j , k ) (i,j,k) (i,j,k),其中 1 ≤ i < j < k ≤ n 1\le i<j<k\le n 1i<j<kn,如果 a i , a j , a k a_i,a_j,a_k ai,aj,ak是不升或者不降的序列,那么这三个点就能构造坏三元组。

所以问题就转化成为了,找出有多少个子数组中不存在非升或非降的三元组。

再仔细观察一下,可以发觉对于任何一个好数组,最大的长度是4,一但长度大于4,就一定会出现一个坏三元组。

所以我们可以通过从左向右遍历整个数组,枚举一下从当前位最多向前延伸多长,这个长度即为以当前元素作为最后子数组结尾的个数,累加起来即可。

看似有多层循环,但因为好数组长度的限制,所以在向前延伸的循环并不会执行太多次,时间复杂度还是线性的。

代码:
#include<cstdio>
const int N=2e5+10;
int a[N];
int n;
bool check(int l,int r){
    if(r-l+1<=2) return true;
    for(int i=l;i+2<=r;i++)
        for(int j=i+1;j+1<=r;j++)
            for(int k=j+1;k<=r;k++)
                if((long long)(a[i]-a[j])*(a[j]-a[k])>=0) return false;
    return true;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        int res=0;
        for(int i=1;i<=n;i++){
            int j=i;
            bool flag=true;
            while(j>=1){
                if(!check(j,i)) break;
                j--;
            }
            res+=(i-j);
        }
        printf("%d\n",res);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值