Educational Codeforces Round 69 A-E

A. DIY Wooden Ladder

先找出数组中最大的两个元素a和b,b是第二大的数。答案是min(b-1,n-2)

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 100010;
int arr[N];
#define min(a,b) ((a)<(b)?(a):(b))
int main()
{
#ifdef CODEBLOCKS
    freopen("in.txt","r",stdin);
#endif
    int t;
    cin>>t;
    for(int ti=0; ti<t; ti++)
    {
        int n;
        cin>>n;
        int a=-1,b=-1;
        for(int i=0; i<n; i++)
        {
            cin>>arr[i];
            if(arr[i]>a)
            {
                b=a;
                a= arr[i];
            }
            else if(arr[i]>b)
            {
                b=arr[i];
            }
        }
        int ret = min(b-1,n-2);
        if(ret<0)
            ret = 0;
        cout<<ret<<endl;
    }
    return 0;
}

B. Pillars

首先找出最大的元素a_i,目标是将所有盘子移到i处。如果对于j<k<i,a_j>a_k,那么盘子j将无法移到柱子i。同理如果j>k>i,a_j>a_k也会导致所有盘子无法移到i处。找到最大元素a_i后向左向右遍历一遍即可。

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 2*100010;
int n;
int arr[N];
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
bool solve()
{
    int ti = -1;
    int t = -1;
    for(int i=0;i<n;i++)
    {
        if(arr[i] > t)
        {
            t = arr[i];
            ti = i;
        }
    }
    int a = t;
    for(int i=ti-1;i>=0;i--)
    {
        int x = arr[i];
        if(x>=a)
        {
            return false;
        }
        a = min(x, a);
    }
    a = t;
    for(int i=ti+1;i<n;i++)
    {
        int x = arr[i];
        if(x>=a)
        {
            return false;
        }
        a=min(x,a);
    }
    return true;
 
}
int main()
{
    #ifdef CODEBLOCKS
    freopen("in.txt","r",stdin);
    #endif
    while(cin>>n)
    {
 
        for(int i=0;i<n;i++)
        {
            cin>>arr[i];
        }
 
        if(solve())
        {
            cout<<"YES"<<endl;
        }
        else
        {
            cout<<"NO"<<endl;
        }
    }
 
    return 0;
}

C. Array Splitting

对于分好后的第x个连续子数组a_i,a_{i+1},a_{i+2},...,a_{i+j}max(x) = a_{i+j}-a_i = a_{i+j} - a_{i+j-1} + a_{i+j-1} - a_{i+j-2}+...+a_{i+2}-a_{i+1}+a_{i+1}-a_i

当k=1时,所求答案为\Sigma_{x=1}^{n-1}a_{x+1}-a_{x}

当k=2时,假设分区是1~i,i+1~n,则答案是\Sigma_{x=1}^{i-1}(a_{x+1}-a_{x}) + \Sigma_{x=i+1}^{n-1}(a_{x+1}-a_{x}) = \Sigma_{x=1}^{n-1}(a_{x+1}-a_{x}) - (a_{i+1} - a_{i})

以此类推,答案应该为\Sigma_{x=1}^{n-1}(a_{x+1}-a_{x})减去k-1个最大的(a_{i+1} - a_{i})

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 3*100010;
int arr[N];
int q[N];
int n,k;
 
#define min(a,b) ((a)<(b)?(a):(b))
int main()
{
#ifdef CODEBLOCKS
    freopen("in.txt","r",stdin);
#endif
    while(cin>>n>>k)
    {
        for(int i=0;i<n;i++)
        {
            cin>>arr[i];
            if(i>0)
            {
                q[i-1]=arr[i]-arr[i-1];
            }
        }
        sort(q,q+n-1);
        long long sum = 0;
        for(int i=0;i<n-k;i++)
        {
            sum+=q[i];
        }
        cout<<sum<<endl;
    }
    return 0;
}

D. Yet Another Subarray Problem

best[i]为子数组以第i个元素结尾所能得到的最佳答案。
分两种情况。考虑j>i-m,j~i的子数组的花费为\Sigma_{t=j}^i a_t - k。而对于所有j<=i-m时,j~i的子数组最小花费为best[i-m]+ \Sigma_{t=i-m+1}^i a_t - k。best[i]取两者答案的最小值。算法时间复杂度为O(nm)

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;
const int N = 3*100010;
int arr[N];
long long best[N];
int n,m,k;
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
int main()
{
#ifdef CODEBLOCKS
    freopen("in.txt","r",stdin);
#endif
    while(cin>>n>>m>>k)
    {
        long long ret = 0;
        for(int i=0;i<n;i++)
        {
            cin>>arr[i];
            best[i] = max(0, arr[i]-k);
            ret = max(ret,best[i]);
        }

        for(int i=1;i<n;i++)
        {
            long long t = 0;
            for(int j=0;j<m &&i-j>= 0;j++)
            {
                t += arr[i-j];
                best[i] = max(best[i], t-k);
            }
            if(i>=m)
            {
                best[i] = max(best[i], t-k+best[i-m]);
            }
            ret = max(best[i], ret);
        }
        cout<<ret<<endl;
    }
    return 0;
}

E. Culture

对所有数据以(in_i, out_i)排序。
dp[i] = (extraspace_i, count_i),其中extraspace_i表示以i-n所有套娃构造所能组成的最小extraspace,count_i表示以i-n所有套娃构造所能组成的满足条件的套娃数目。

倒序遍历数据,对于(in_i, out_i),找到恰好大于(out_i, 0)的位置pos,那么对于套娃i应该能装在pos-n中的某些套娃中,其extraspace应该等于dp[pos].extraspace + out_i - in_i

那么对于dp[i]的计算,分三种情况。
a. extraspace > dp[i+1].extraspace时,说明第i个套娃无法与其他套娃构造成最小extraspace,不纳入计算,dp[i] = dp[i+1]

b. extraspace == dp[i+1].extraspace时,第i个套娃应该可以构造出dp[pos].count个满足条件的套娃。dp[i].extraspace = extraspace\\ dp[i].count = dp[pos].count + dp[i+1].count

c. extraspace < dp[i+1].extraspace时,dp[i].extraspace = extraspace\\ dp[i].count = dp[pos].count

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
int n;
const int N = 2*1e5+10;
pair<int, int> p[N];
pair<int, long long> dp[N];
const int mod = 1e9+7;
int main()
{
#ifdef CODEBLOCKS
    freopen("in.txt", "r", stdin);
#endif // CODEBLOCKS
    while(cin>>n)
    {
        int min_out = 0x7fffffff;
        for(int i=0;i<n;i++)
        {
            int a,b;
            cin>>a>>b;
            p[i] = make_pair(b,a);
        }
        sort(p, p+n);
        for(int i=n-1;i>=0;i--)
        {
            int in = p[i].first;
            int out = p[i].second;
            auto iter = lower_bound(p, p+n, make_pair(out,0));
            int space, cnt;
            if((iter-p) == n)
            {
                space = in;
                cnt = 1;
            }
            else
            {
                space = dp[iter - p].first - out + in;
                cnt = dp[iter-p].second;
            }
 
            if(i<n-1)
            {
                if(space > dp[i+1].first)
                {
                    space = dp[i+1].first;
                    cnt = dp[i+1].second;
                }
                else if(space == dp[i+1].first)
                {
                    cnt = (cnt + dp[i+1].second)%mod;
                }
            }
            dp[i] = make_pair(space, cnt);
        }
        cout<<dp[0].second<<endl;
    }
    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容

  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,339评论 0 2
  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 8,981评论 0 13
  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,371评论 0 4
  • 大学客沙龙第三十五期,我们特邀请香港理工大学校友陕西睿成财税咨询有限公司总经理宋海洋给大家分享,本次主题是《企...
    西安大学客阅读 261评论 0 0
  • 工作中现在有一个很大的问题,就是回邮件太慢,一个邮件少则半小时,多则1,2个小时。 中文的都还好,主要是英文。自己...
    七年新生阅读 95评论 0 0