码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #616 (Div. 2)

时间:2020-02-03 18:53:55      阅读:52      评论:0      收藏:0      [点我收藏+]

标签:include   display   push   复杂度   --   是什么   div   否则   lap   

题目链接:https://codeforces.com/contest/1291

A - Even But Not Even

题目大意:定义ebne类型,如果一个数本身不是2的倍数,且所有数字的和为2的倍数记为ebne。现在给你一个长度小于等于3000的数字,判断是否能通过删除操作将其变为ebne类型。t组数据,n,接下来长度为n的数字。

Example:

input
4
4
1227
1
0
6
177013
24
222373204424185217171912
output
1227
-1
17703
2237344218521717191

 不用想得太复杂,题目没有要求剩下的数是什么,我们只要记录一下奇数的个数就好了,如果奇数的个数小于等于1,那么就无解。否则的话我们直接放两个奇数上去就完事了

以下是AC代码:

技术图片
#include <bits/stdc++.h>
using namespace std;

const int mac=1e6+10;

char s[3010];
int mk[3010];

int main(int argc, char const *argv[])
{
    int t,n;
    scanf ("%d",&t);
    while (t--){
        scanf ("%d",&n);
        scanf("%s",s);
        for (int i=0; i<=n; i++) mk[i]=0;
        int cnt=0;
        for (int i=0; i<n; i++){
            if ((s[i]-0)%2) mk[++cnt]=s[i]-0;
        }
        if (cnt<=1) printf("-1\n");
        else printf("%d%d\n",mk[1],mk[2]);
    }
    return 0;
}
View Code

 

B - Array Sharpening

题目大意:给你一个非负数列a,问是否存在一个峰顶x,使得$a_{1}<a_{2}<...<a_{x}>a_{x+1}>a_{x+2}>...>a_{n}$。t组数据,n,n个数

Example:

input
10
1
248618
3
12 10 8
6
100 11 15 9 7 8
4
0 1 1 0
2
0 0
2
0 1
2
1 0
2
1 1
3
0 1 0
3
1 0 1
output
Yes
Yes
Yes
No
No
Yes
Yes
Yes
Yes
No

我们可以先做两个最小代价的上升序列即0到n-1和n-1到0。

我们假设峰顶为x,那么如果Yes的话在x之前一定成立$a_{i}>=i-1$,在x之后一定成立$a_{i}>=n-i$

我们从前往后找到最后一个$a_{i}>=i-1$的位置记为in_pos,从后往前找到最后一个$a_{i}>=n-i$的位置记为de_pos,那么如果in_pos>=de_pos那么也就是说他们可以成功衔接,即答案为Yes

以下是AC代码:

技术图片
#include <bits/stdc++.h>
using namespace std;

const int mac=3e5+10;

int a[mac],b[mac],c[mac];

int main()
{
    int t,n;
    scanf ("%d",&t);
    while (t--){
        scanf ("%d",&n);
        for (int i=1; i<=n; i++){
            scanf("%d",&a[i]);
            b[i]=i-1;
        }
        int cnt=0;
        for (int i=n; i>=1; i--) c[i]=cnt++;
        int end_inc=0,end_dec=0;
        for (int i=1; i<=n; i++){
            if (a[i]>=b[i]) end_inc=i;
            else break;
        }
        for (int i=n; i>=1; i--){
            if (a[i]>=c[i]) end_dec=i;
            else break;
        }
        if (end_inc>=end_dec) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
View Code

 

C - Mind Control

 题目大意:t组数据,n,m,k(数列大小,你的位置,你能控制的人数)。每个人能够删除数列的头或尾,删除一次后出队,问轮到你删数的时候,你能够删除的最大的数至少是多少?其中你能够控制k个人按照你的方法来删头还是尾。

Example
input
4
6 4 2
2 9 2 3 8 5
4 4 1
2 13 60 4
4 1 3
1 2 2 1
2 2 0
1 2
output
8
4
1
1

你能够控制x人,那么你不能控制的人为y,假设这y个人是被别人控制的,你要获得的是最大的值那么他一定会阻止你。但因为只能拿头和尾就好办了,我们假设在头部拿了0-x个(i),那么对手可以在头部拿0-y个(j),由于对手要阻止你,那么他一定会使你拿到最小的,所以我们枚举对手拿的数量,取答案最小的值就是当我们控制拿i个头时的解,然后我们取每个头的最大值就可以了。当那i,j个头的时候,尾巴会被拿x-i,y-j个,所以每次枚举的时候我们取的是$min(a[i+j],a[n-1-(x-i)-(y-j)])$

以下是AC代码:

技术图片
#include <bits/stdc++.h>
using namespace std;

const int mac=4e3+10;
const int inf=1e9+10;

int a[mac];

int main(int argc, char const *argv[])
{
    int t,n,pos,control;
    scanf ("%d",&t);
    while (t--){
        scanf ("%d%d%d",&n,&pos,&control);
        int before=pos-1;
        int nbcontrol=min(before,control);
        for (int i=0; i<n; i++) scanf("%d",&a[i]);
        int ans=0;
        for (int i=0; i<=nbcontrol; i++){
            int stp_ans=inf;
            for (int j=0; j<=before-nbcontrol; j++){
                int ans1=max(a[i+j],a[n-1-(nbcontrol-i)-(before-nbcontrol-j)]);
                stp_ans=min(stp_ans,ans1);
            }
            ans=max(ans,stp_ans);
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

当然$O(n^{2})$的复杂度还是不够好,实际上我们可以利用数据结构deque优化对手拿的情况从而将时间优化到$O(n)$

我们先预处理拿0-(m-1)个头的时候的解:

for (int i=0; i<m; i++)
     b[cnt++]=max(a[i],a[i+n-m]);

利用deque保存对手拿到的头的位置,那么一旦拿到某个位置的时候我们就不需要对对方枚举之前的了,那么时间就大大减少。

由于之前我们已经预处理出了拿到i时的解,所以我们枚举对手拿到的位置的时候我们只需要保留在对手扫过的一段中的最小值就好了:

deque<int> q;
for(int i = 0, j = 0; i <= k; i++) {//可控的前k个
    while(q.size() && q.front() < i)//已经在头拿了i个了,那么i之前的位置已经没用了
        q.pop_front();
    while(j < i + sz) {//对手拿到的头的位置+1
        while(q.size() && b[q.back()] >= b[j])//如果新的位置的解更小,那么之前的位置出队
            q.pop_back();
        q.push_back(j++);
    }
    ans = max(ans, b[q.front()]);
}

于是一个线性复杂度的解法就诞生了!

以下是AC代码:

技术图片
#include <bits/stdc++.h>
using namespace std;

const int mac=4e3+10;

int a[mac],b[mac];

int main(int argc, char const *argv[])
{
    int t,n,pos,control;
    scanf ("%d",&t);
    while (t--){
        scanf ("%d%d%d",&n,&pos,&control);
        int before=pos-1;
        int nbcontrol=min(before,control);
        int discontrol=before-nbcontrol;
        for (int i=0; i<n; i++) scanf ("%d",&a[i]);
        int cnt=0;
        for (int i=0; i<pos; i++) b[cnt++]=max(a[i],a[i+n-pos]);
        deque<int>q;
        int ans=0;
        for (int i=0,j=0; i<=nbcontrol; i++){
            while (q.size() && q.front()<i)
                q.pop_front();
            while (j<i+discontrol+1){
                while (q.size() && b[q.back()]>=b[j])
                    q.pop_back();
                q.push_back(j++);
            }
            ans=max(ans,b[q.front()]);
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

D - Irreducible Anagrams

 

E - Prefix Enlightenment

 

F - Coffee Varieties (easy version)

 

Codeforces Round #616 (Div. 2)

标签:include   display   push   复杂度   --   是什么   div   否则   lap   

原文地址:https://www.cnblogs.com/lonely-wind-/p/12255725.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!