首页 > 其他分享 >Educational Codeforces Round 147

Educational Codeforces Round 147

时间:2023-04-24 19:55:28浏览次数:45  
标签:147 Educational int MAX scanf Codeforces ans 区间 using

A

题意

思路

有前导零结果直接为0,出现在第一位的贡献为9,其他地方的贡献为10

代码

#include<bits/stdc++.h>
 
using namespace std;
using ll=long long;
 
char s[10];
 
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s);
        if(s[0]=='0')
        {
            printf("0\n");
            continue;
        }
        int res=s[0]=='?'?9:1;
        for(int i=1;i<strlen(s);i++)
            if(s[i]=='?')res*=10;
        printf("%d\n",res);
    }
}

B

题意

给一个数组,对其进行一次如下操作:选一个区间,然后将这个区间进行从小到大排序。现在给出操作前和操作后的数组,求可能选择的最长区间是哪里。

思路

刚开始想到可以直接找最长不降子串,但是实际上区间不一定是最长不降子串,因为有可能数组中本身存在一个长的不降区间,但是并没有选择这个区间操作。

所以想到可以先找到一个区间[l,r],使得l,r位置修改前后的值不相等,然后再在修改后的数组中,向左向右扩展,扩展到可以得到的最大不降子串。因为可以等价于选择了扩展后的区间操作。

代码

#include<bits/stdc++.h>
 
using namespace std;
 
const int MAX=2e5+5;
 
int a[MAX],b[MAX];
 
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            scanf("%d",&a[i]);
        for(int i=0; i<n; i++)
            scanf("%d",&b[i]);
       int l=0,r=n-1;
       while(a[l]==b[l])l++;
       while(a[r]==b[r])r--;
       while(l>0&&b[l-1]<=b[l])l--;
       while(r<n-1&&b[r+1]>=b[r])r++;
       printf("%d %d\n",l+1,r+1);
    }
}

C

题意

给一个小写字母组成的字符串,每次可以删除其中的任意字符,但是选择删除的字符位置不能相邻。求最少多少次操作可以使得字符串只剩下相同的某个字母。

思路

首先可以想到,操作一定有一个上限,那就是每次选择奇数或偶数位置的字符删除,最后留下一个字母,设字符串长度为length,操作次数的上限为

\[\lfloor log_2(length) \rfloor \]

然后可以想到,由于总共只有26个字母,那么可以枚举最后剩下哪个字母,其他的全部删除。枚举留下的字母,然后以当前字母为分隔符,将字符串分块,将各块全部删除,操作次数就是删除最长的分块需要的操作次数。根据上述的结论,这个操作次数为

\[\lfloor log_2(length) \rfloor+1 \]

因为要把最后剩的一个字符也删除。

代码

#include<bits/stdc++.h>
 
using namespace std;
 
const int MAX=2e5+5;
 
char s[MAX];
vector<int>pos[26];
 
int left1(int n)
{
    int res=28;
    while(((1<<res)&n)==0)res--;
    return res+1;
}
 
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        for(int i=0;i<26;i++)
            pos[i].clear();
        scanf("%s",s);
        int n=strlen(s),minn=n;
        for(int i=0;i<n;i++)
            pos[s[i]-'a'].push_back(i);
        for(int i=0;i<26;i++)
        {
            int last=-1,maxx=0;
            pos[i].push_back(n);
            for(int j=0;j<pos[i].size();j++)
            {
                maxx=max(maxx,pos[i][j]-last-1);
                last=pos[i][j];
            }
            minn=min(minn,maxx);
        }
        if(minn==0){printf("0\n");continue;}
        printf("%d\n",left1(minn));
    }
}

D

题意

给一个1*inf的格子条,以及一系列区间,区间互不相连,从左到右移动,每次在区间内,可以按下按钮开始染色,然后松开按钮停止染色,区间外不能染色。每移动一格,代价为1,按下和松开按钮代价也均为1。求最少代价,使得总共染色格子数量为k

思路

决策的点就在于要不要跳过一些区间,由于区间不连续,那么从一个区间末端到下一个区间起点最少需要2的代价。然后很明显可以想到,只要区间长度>=2,那么就没必要跳过,因为如果跳过任意一个长度>=2的区间,那么尽管减少了按下和松开按钮的代价(共为2),但是收益也至少减少了2,那么在之后的区间中就必须至少额外染色2个格子,相当于代价增加了2,因此跳过不会带来收益。

只有跳过长为1的区间会带来收益,所以可以想到统计长为1的区间个数,遍历区间,每遇到染色格子数量>=k时,就尝试用当前的区间额外长度替换之前的长为1的区间,可以减少按按钮的代价,最后整体取最优解。

#include<bits/stdc++.h>
 
using namespace std;
 
const int MAX=2e5+5;
 
int l[MAX],r[MAX];
 
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,k;
        scanf("%d%d",&n,&k);
        int cur=0,ans=2e9+7,cnt1=0;
        for(int i=0;i<n;i++)
            scanf("%d",&l[i]);
        for(int i=0;i<n;i++)
            scanf("%d",&r[i]);
        for(int i=0;i<n;i++)
        {
            int len=(r[i]-l[i]+1);
            if(len==1)cnt1++;
            cur+=len;
            if(cur>=k)
            {
                int remain=cur-k;
                int mincnt=min(cnt1,remain);
                ans=min(ans,(i+1-mincnt)*2+r[i]-remain+mincnt);
            }
        }
        if(ans==2e9+7)ans=-1;
        printf("%d\n",ans);
    }
}

标签:147,Educational,int,MAX,scanf,Codeforces,ans,区间,using
From: https://www.cnblogs.com/cryingrain/p/17350688.html

相关文章

  • Educational Codeforces Round 147 (Rated for Div. 2)
    题目链接B核心思路真的需要加强了,看到这个最大值和最小值我们其实也需要往对应的最大值和最小值的相关操作去想,不如前缀最小值/前缀最大值或者是后缀最小值/后缀最大值。这里一个比较直接的想法就是想找到不同的地方,然后看不可以扩展。那么怎么看是否可以扩展呢,如果是左边的话......
  • Educational Codeforces Round 127 (Rated for Div. 2)
    题目链接D核心思路首先挖掘下操作的性质吧:x>1&&x+3<10:1xx+1x+2x+310我们可以发现这样子好像对于我们的结果是没有影响的,答案还是9.所以这个性质就挖掘出来了啊,只要我们把一段连续的插入到对应的区间里面就好了。也就是只要这个区间的左端点小于插入连续的数的最小值,......
  • Codeforces Beta Round 96 (Div. 1) -- C. Logo Turtle (dp,记忆化搜索)
    记忆化搜索就是暴力,多一步优化,走过的路别走了。说实话,可能是数据水了,居然能过。constintN=510;strings;intn,ans;boolst[501][501][2][50];voiddfs(intx,intidx,intdir,intk){ if(st[x][idx][dir][k])return; st[x][idx][dir][k]=1;//走过的路不走......
  • Educational Codeforces Round 147 (A-D)
    A.Matching橘子熊:这题太简单了我不想写题面Description给定给一个带问号的字符串,求有多少种可能的数字Input多次询问,一次一个字符串Output对于每次询问,输出可能的数字的总数数据范围与约定2e5次询问,单词询问不超过5个字符思路主要思路签到题大部分情况下,一个......
  • Educational Codeforces Round 39 (Rated for Div. 2) -- D. Timetable (DP)
    写得很折磨人,每次dp都写个一个多小时,写出来明明觉得不难.题目大意:可以进行K次操作,把删除1,进行k次操作后每行第一个1和最后一个1的位置相减的绝对值加1得到的结果最小。做法:每次肯定是要从左删或者从右边删,然后顺着这个思路,先把每行的进行小于等于k次操作时,每行最小......
  • codeforces 559C Gerald and Giant Chess(dp+组合数学)
    题目链接:codeforces559C题目大意:给出一个h*r的矩阵,从左上角走到右下角,中间有一些点不能经过,问不同的路径有多少种?题目分析:首先我们考虑一个n*m的矩阵,从左上角只能向右或向下走能走到右下角的方案数,也就是C(n+m,n),就是一共要走n+m次,选出n次横着走。那么我们定义dp[i]表示在前不经......
  • codeforces 545C C. Woodcutters(dp+二分)
    题目链接:codeforces545C题目大意:给出一些树的位置和高度,每棵树可以砍倒,覆盖[xi−hi,xi]或者覆盖[xi,xi+hi],或者不砍倒,问最多砍倒多少棵树?题目分析:我们记录dp[i]表示选取到i棵树的时候用的最短的区间长度。每次枚举每棵树,二分到最大的不超过当前树位置的个数,然后利用当前树的信息......
  • codeforces 4D D. Mysterious Present(dp)
    题目连接:codeforces4D题目大意:给出n个信封,这n个信封有长和宽,给出卡片的尺寸,求取能够装入卡片的最长的序列,序列满足后一个的长和宽一定大于前一个,求最长的这个序列的长度,并且给出一组可行解。题目分析:一看这种题目就是dp的题目,状态定义dp[i]为以i结尾的序列的最大的长度,并且利用一......
  • codeforces 2B B. The least round way(dp+数论)
    题目链接:codeforces2B题目大意:给出一个n*n的矩阵,从左上角走到右下角,只能向右或向下走,问路径上的数之积末尾0最少的方案是什么。题目分析:首先我们要做两个预处理,处理出每个位置上的数包含多少个2的质因子和多少个5这个质因子然后我们统计路径上弄到最少的2的方案数和最少的5的方案......
  • codeforces 126B B. Password(kmp+dp)
    题目链接:codeforces126B题目大意:给出一个字符串,找出一个子串既是它的前缀,也是它的后缀,还是一个非后缀也非前缀的子串。题目分析:本来挺简单的一个题,最开始想复杂了,还用了后缀数组,醉了。这个题主要用的是kmp的next数组,首先我们要了解next数组的定义,next[i]表示以i为末尾的子串的后缀......