Codeforces Round #506 (Div. 3)

 

目录

            A. Many Equal Substrings

            B. Creating the Contest

            C. Maximal Intersection


     

                                  A. Many Equal Substrings

You are given a string t consisting of n lowercase Latin letters and an integer number k

Let's define a substring of some string s with indices from l to r as s[l…r].

Your task is to construct such string s of minimum possible length that there are exactly k positions i such that s[i…i+n−1]=t. In other words, your task is to construct such string s of minimum possible length that there are exactly k substrings of s equal to t.

It is guaranteed that the answer is always unique.

传送门

大致题意:给出一个 长度为n的字符串s,要求输出一个含有k个s的字符串

Input

3 4
aba

Output

ababababa

Input

3 2
cat

Output

catcat

一道很水的签到题,既然暴力就能过(n,k<=50),那我们不如就打个暴力。

暴力枚举最长的重复的子串,比如样例中'a'重复了。

我们将原字符串去除这个重复的字符串"aba"->"ab"然后输出k次。

再在结尾输出重复的字串'a'。

有人说:"我觉得布星,你这一点都不暴力,你说打暴力就打出最暴力的东西给我看啊!"。

无可奉告  好了够暴力了吧?

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,k,ans=0;
string s;
int main()
{
    cin>>n>>k;
    cin>>s;
    int l=s.size();
    for(register int i=l-1;i;--i)
    {
        bool flag=0;
        for(register int j=0;j<i;++j)
            if(s[j]!=s[l-i+j])
                {flag=1;break;}
        if(flag==0){ans=i;break;}
    }
    if(ans!=0)
    {
        for(register int i=1;i<=k;++i)
            for(register int j=0;j<l-ans;++j)
                cout<<s[j];
        for(register int i=0;i<ans;++i)
            cout<<s[i];
    }
    else
    {   
        for(register int i=1;i<=k;++i)
            cout<<s;
    }           
    return 0;
}

 

                                              B. Creating the Contest

You are given a problemset consisting of n problems. The difficulty of the i-th problem is ai. It is guaranteed that all difficulties are distinct and are given in the increasing order.

You have to assemble the contest which consists of some problems of the given problemset. In other words, the contest you have to assemble should be a subset of problems (not necessary consecutive) of the given problemset. There is only one condition that should be satisfied: for each problem but the hardest one (the problem with the maximum difficulty) there should be a problem with the difficulty greater than the difficulty of this problem but not greater than twice the difficulty of this problem. In other words, let ai1,ai2,…,aip be the difficulties of the selected problems in increasing order. Then for each j from 1 to p−1 aij+1≤aij*2 should hold. It means that the contest consisting of only one problem is always valid.

Among all contests satisfying the condition above you have to assemble one with the maximum number of problems. Your task is to find this number of problems.

传送门

大致题意:给出n个单调递增的数,求出最长的一个满足下列条件的序列,输出它的长度。

条件:在此序列中,对于任意一个数ai(除去最大的那个数),存在至少一个数aj>ai并且aj<=ai*2。(序列不需要连续)

样例

输入

10
1 2 5 6 7 10 21 23 24 49

输出

4

最长的序列为5,6,7,10。

n<=2e5

给人的感觉来看这道题比第一题还水(可能是因为我第一题打的暴力)。

为什么cf给的标签是dp和贪心,还有数学?????。

我感觉我写的比题解还简单emmmmmm。

由于单调递增的特性,所以满足条件的序列肯定是连续的。

假设a[i]>a[i-1]*2,那么a[i+1],a[i+2]......a[n]>a[i],所以a[i+1],a[i+2]......a[n]>a[i-1]*2。

所以a[i]以及a[i]之后的数都不能算入之前包含a[i-1]的序列当中。

(题面里面还说不要求连续,毒瘤出题人)

所以既然答案连续,每次只用判断当前数是否满足上一个数,并且保留当前已经满足条件的最长的序列的长度。

如果满足了,那么长度++。如果不满足,之后的数就都不满足了。

我们就从这个数开始,开设一个新的序列,去判断它最大长度。

那只需要O(n)扫一遍好了啊!(数据完全可以1e8啊!)。

为什么这么简单我要说这么多???

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[200005],ans=0;
int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n;
    for(register int i=1;i<=n;++i)
        cin>>a[i];
    int tot=1;
    for(register int i=2;i<=n;++i)
    {
        if(a[i]<=a[i-1]*2)
            ++tot;
        else
        {
            ans=max(ans,tot);
            tot=1;
        }
    }
    ans=max(ans,tot);
    cout<<ans;
    return 0;
}

                                            C. Maximal Intersection

 

You are given n segments on a number line; each endpoint of every segment has integer coordinates. Some segments can degenerate to points. Segments can intersect with each other, be nested in each other or even coincide.

The intersection of a sequence of segments is such a maximal set of points (not necesserily having integer coordinates) that each point lies within every segment from the sequence. If the resulting set isn't empty, then it always forms some continuous segment. The length of the intersection is the length of the resulting segment or 0 in case the intersection is an empty set.

For example, the intersection of segments [1;5] and [3;10] is [3;5] (length 2), the intersection of segments [1;5] and [5;7] is [5;5] (length 0) and the intersection of segments [1;5] and [6;6] is an empty set (length 0).

Your task is to remove exactly one segment from the given sequence in such a way that the intersection of the remaining (n−1)

segments has the maximal possible length.

传送门

Input

4
1 3
2 6
0 4
3 3

Output

1

Input

5
2 6
1 3
0 4
1 20
0 4

Output

2

简单翻译一下:给出n条线段Ai的左端点 Li 和右端点 Ri ,求删除一条线段后剩下线段的交集长度Lenth最大。

 

我感觉这些题目都是第一眼看上去很简单,开始写的时候经常会不好写,但是当你思考一下之后又变得简单起来。

我们考虑贪心。

很容易可以判断出,原先n条线段的交集=所有线段右端点的最小值Rmin - 所有线段左端点的最大值Lmax。

我们只需要O(n)来计算删除每个线段之后所带来的影响。

假设当前线段Ai的左端点为Li,右端点为Ri。

如果Li<Lmax且Ri>Rmin,那么删除这条线段不会造成任何影响。

如果Li=Lmax 删除这条线段后,将Lmax变为Lmax'(所有线段的第二大的左端点)。然后ans=max(Rmin-Lmax')。

如果Ri=Rmax 同理,将Rmin变为Rmin'再进行计算。

大多数情况都可以在样例中发现,良心出题人(你上一题说的什么来着?)。

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,l[300005],r[300005],x[300005],y[300005],ans=0;
int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n;
    for(register int i=1;i<=n;++i)
    {
        cin>>l[i]>>r[i];
        x[i]=l[i];
        y[i]=r[i];
    }
    sort(x+1,x+n+1);
    sort(y+1,y+n+1);
    for(register int i=1;i<=n;++i)
    {
        int lmax=x[n],rmin=y[1];
        if(l[i]==lmax) lmax=x[n-1];
        if(r[i]==rmin) rmin=y[2];
        ans=max(ans,rmin-lmax); 
    }
    cout<<ans;
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值