第二次训练赛

第二次训练赛

自己当时做出来的就没往上补。

A - 构造最长递增子串

这道题的意思就是输入一串字符串,然后你可以在其中修改一个字符,使其可以得到一个最长的连续递增的字符串;

这道题我用自己的方法做了两天没做出来,就去看了题解,下面是我看懂后自己按着题解的思路写的代码:

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
int main(){
 int a[100005];
 int n;
 while(scanf("%d",&n)!=EOF){
  int t=0;
  for(int i=1;i<=n;i++){
   scanf("%d",&a[i]);
  }
  int b[100005],c[100005];
  b[0]=0,b[n+1]=0;      //全都初始化(很重要)要不很容易最后结果非常大; 
  c[0]=0,c[n+1]=0;
  a[0]=0,a[n+1]=0;
  for(int i=1;i<=n;i++){     //从左往右找连续区间; 
   if(a[i]>a[i-1]) b[i]=b[i-1]+1;
   else b[i]=1;
  }
  for(int i=n;i>0;i--){      //从右往左找连续去间; 
   if(a[i]<a[i+1]) c[i]=c[i+1]+1;
   else c[i]=1; 
  }
  for(int i=1;i<=n;i++){
   if(a[i-1]+1<a[i+1]) t=max(t,b[i-1]+c[i+1]+1);     //如果改变a[i]的值可以衔接两边的区间就按两边区间和来比较; 
   else t=max(t,max(b[i-1]+1,c[i+1]+1));     //如果不能那就选两边的区间,每个区间再加上这个,即长度就为两边区间长+1; 
  }
  printf("%d\n",t);
 }
}

下面的代码就是我思考两天后的结果,洛谷上只能对前26个,哪位大佬如果有时间,可以帮我看看是哪错了(非常感谢):

#include<iostream>
using namespace std;
int main(){
 int a[100005];
 int n;
 while(cin>>n){
  for(int i=0;i<n;i++){
  cin>>a[i];
 }
 int maxlen=0,nowlen=1;
 int j=0,z;
 if(n==1){     //先判断数组长度是否为1,直接输出; 
  cout<<1;
  return 0;
 }
 for(int i=1;i<n;i++){
  if(a[i]>a[i-1]){      //找连续的长度 ; 
   if(j>=1){     //判断是否已经改变过一个数; 
    if(a[i]>a[z-1]+j){    //这个是当j>1时,即已经改变一个数后,这个数后面的数一定要比改变后的数大,我这里默认的改变的值之比前一个书大1; 
     j++;   //每次往后一个数就要比改变数的前一个数大1,大2,大3····; 
     nowlen++;    //区间长度+1; 
    }
    else nowlen=1;     //如果不符合连续的要求,区间变为1; 
   }
   else if(j==0) nowlen++;     //如果没改过那就直接区间长度+1; 
  }
  else if(a[i]<=a[i-1]&&j==0){    //如果这个数比上一个小并且没有改过数字,那就将此数字放进区间当作改变的数; 
   nowlen++;
   z=i;     //此次寻找连续递增区间结束后,下次的i就要从这个数字的后一个开始; 
   j++;     //标记下已经改过一次数字; 
  }
  else{
   nowlen=1;     //如果都不符合,区间长度清为1; 
   j=0;        //标记初始化; 
   i=z;       //此次循环从上次改过的数字的下一个开始; 
  }
  if(nowlen>maxlen){
   maxlen=nowlen;
  }
 }
 cout<<maxlen;
 } 
 return 0;
} 

B - Is it beautiful?

这道题最重要的是读懂题目的意思!!!!

这个题的意思就是从1开始一直到n。1,1-2,1-3.。。。1-n,若是每组数所对应的位置也可以组成一个连续求相邻的排列,那此时相应的位置输出1(比如说1-6符合条件,那第6个位置输出1),否则输出0;

需要用到的知识点:
要组成连续的数列,最大值和最小值的差距必须是n-1;

代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
struct bh{
 int num;
 int p;
}a[200007];
bool cmp(bh a,bh b){
 return a.num<b.num;
}
int main(){
 int t;
 cin>>t;
 int b[200007];
 while(t--){
  int n;
  cin>>n;
  for(int i=1;i<=n;i++){
   cin>>a[i].num;     //记录输入的数; 
   a[i].p=i;      //并且记录下位置; 
  }
  sort(a+1,a+n+1,cmp);      //按num从小到大排列; 
  b[1]=1;      //1一定符合条件; 
  int ma=a[1].p;     //给最大最小初始位置为a[1]的初始位置; 
  int mi=a[1].p;      
  for(int i=2;i<=n;i++){     //因为1已经确定所以我们从2开始; 
   ma=max(ma,a[i].p);     //不断更新此时初始位置的最大最小值; 
   mi=min(mi,a[i].p);
   if(ma-mi==i-1) b[i]=1;     //如果符合上述知识点中的条件,既符合题目条件; 
   else b[i]=0;
  }
  for(int i=1;i<=n;i++){
   cout<<b[i];
  }
  cout<<endl; 
 }
} 

C - Juicer

还没有搞懂。。。

D - Eat Candies

题意为:有三种不同的糖每天只能吃两种不同的糖且每种糖只能吃一个,问怎多能够吃多少天。

解题思路:(因为我看了洛谷上的题解,所以此题的思路和洛谷上的大致相同题解链接!!!
先把三种糖按从小到大排序;
此时不妨设一定有x<=y<=z;
此时又可以分为两种情况:
①x+y<z:
那么此时能吃的天数一定为x+y天;
②x+y>=z:
这时又有多种情况,比如说将z吃完后x没了或y没了或两个都没了;或是z吃完后x,y都有剩余···
这时我们就可以来找规律了:
首先我们先把z吃完,你会发现总能有一种情况在吃完z后,x,y相差1或0;
然后通过上述的规律理所当然的就可以发现天数=(x+y+z)/2;

然后可以得到如下的代码:

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
 int t;
 cin>>t;
 while(t--){
  int a[3];
  long long sum=0;
  for(int i=0;i<3;i++) cin>>a[i];
  sort(a,a+3);
  if(a[0]+a[1]<a[2])
  cout<<a[0]+a[1]<<endl;
  else cout<<(a[0]+a[1]+a[2])/2<<endl;
 }
}

E - 由你来决定怎么颁奖

题意:就是给你一大堆成绩让你分配金银铜奖,金奖一定要比银铜奖少,且高等级奖牌的最低成绩一定要比次一等级的最高成绩高;

我们可以让成绩最高的拿金奖,第二高的那银奖,第三高的拿铜奖,然后再看数量是否符合题意,若不合题意:如果是银奖少了那就让第二高和第三高的拿银奖然后就这么以此类推知道符合条件为止。
代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
struct cj{
 int x;
 int num;
}a[400005];
int main(){
 int t;
 cin>>t;
 aa:while(t--){
  int n;
  int j=1;
  cin>>n;
  int x;
  for(int i=1;i<=n;i++){
   cin>>x;
   if(i==1){
    a[j].x=x;
    a[j].num=1;
    continue;
   }
   if(x==a[j].x) a[j].num++;
   else{
    j++;
    a[j].x=x;
    a[j].num=1;
   }
  }
  int jp=a[1].num;
  int yp=0,tp=0,z=2;
  while(yp<=jp&&yp+jp<=n/2){
   yp+=a[z].num;
   z++;
  } 
  while(tp<=jp||yp+tp+jp<n/2){
   tp+=a[z].num;
   z++;
  }
  if(tp+jp+yp>n/2){
   tp-=a[z-1].num;
  }
  if(tp<=jp||yp<=jp) cout<<"0 0 0"<<endl;
  else cout<<jp<<' '<<yp<<' '<<tp<<endl;
 }
}

F - XorXor

xor为异或的意思。
异或:异或,英文为exclusive OR,缩写成xor异或(xor)是一个数学运算符。它应用于逻辑运算。异或的数学符号为“⊕”,计算机符号为“xor”。其运算法则为:a⊕b = (¬a ∧ b) ∨ (a ∧¬b)如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。(详细链接—>https://baike.baidu.com/item/异或/10993677)
题目还没看懂。。。

H - Perfect String

题意:
给你一串只由a,b,c,?组成的字符串,并把?改成a,b或c,并使字符串每两个相邻的元素不相同,如果可以就输出字符串(任意正确答案都可以)若是不行就输出-1.
代码如下:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main(){
 int t;
 cin>>t;
 getchar();
 while(t--){
  char a[100005];
  gets(a);
  int n=strlen(a);
  int i;
  for(i=1;i<n;i++){
   if(a[i]==a[i-1]&&a[i]!='?') break;
  }
  if(i<n){
   cout<<"-1"<<endl;
   continue;
  }
  for(i=0;i<n;i++){
   if(a[i]=='?'){
    if(a[i-1]!='a'&&a[i+1]!='a') a[i]='a';
    else if(a[i-1]!='b'&&a[i+1]!='b') a[i]='b';
    else if(a[i-1]!='c'&&a[i+1]!='c') a[i]='c';
   }
  }
  puts(a);
 }
}
发布了4 篇原创文章 · 获赞 6 · 访问量 368

猜你喜欢

转载自blog.csdn.net/qq_46133691/article/details/103851517