Codeforces #575 div3

A-Three Piles of Candies

题意:给出三堆蜡烛,从第三堆取一些分到前两堆,使前两堆的数量相同。 求这两个堆元素的最大值。

实际上就是三堆数量之和对半分,如果是奇数的话舍去那一个就好。

#include<stdio.h>
#include<algorithm>
using namespace std;
int main(){
    int t; scanf("%d",&t);
    while(t--){
        long long a[3];
        for(int i=0;i<3;i++) scanf("%lld",&a[i]);
        sort(a,a+3);
          printf("%I64d\n",(a[2]-a[1]+a[0])/2+a[1]); 
             //实际上直接输出就好,我做的时候脑抽了 printf("%lld\n",(a[0]+a[1]+a[2])/2); 
    }
    return 0;
}

B- Odd Sum Segments
题意:题中给了一个长度为n的序列,要求划分为k个序列,使每个序列元素之和为奇数(必须是连续序列),试判断是否存在这样的划分方法,不存在直接NO
存在的话将划分点的位置依次输出。
要使要使序列元素之和为奇数,前提是该序列中奇数的个数为奇数个(x>0&&x&1)。而要划分为K个,则前提是原序列中奇数个数必须大于等于k。
所以我们统计序列中奇数的个数,如果比K还小,直接输出就可以;在大于等于K的时候,如果假设k个序列一个序列分配一个奇数,由于奇数加奇数为偶数,如果剩余奇数的个数为偶数个,则一定可以想到办法使他们两两想消,分成符合要求的k个序列。如果剩余奇数个数为奇数个则一定有一个不能抵消影响到已经分配好的序列,此时输出NO。
由于为YES是需要输出划分情况,此时不唯一,我们可以k-1个序列的结束位置与前k-1个奇数在数组中的下标值+1一一对应,最后一个序列一定是第n个直接输出n就可以。

#include<stdio.h>
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,k;
        int a[200010];
        int cnt=0;
        scanf("%d %d",&n,&k);
        for(int i=0;i<n;i++) {
            scanf("%d",&a[i]);
            if(a[i]&1) cnt++;
        }
        if(cnt<k) { //奇数个数小于k
            printf("NO\n");
            continue ;
        }
        else if((cnt-k+1)%2==0) {   //剩余奇数个数为奇数个
            printf("NO\n");
            continue ;
        }
        else {  //可以成功划分的情况
            int num=0;
            printf("YES\n");
            if(k==1) {  //1的时候需要特判
                printf("%d\n",n);
                continue;
            }
            else {  // 按顺序输出即可
                
                for(int i=0;i<n;i++){
                    if(num==k-1) break ;
                    if(a[i]&1) {
                        num++;
                        printf("%d ",i+1);
                    } 
                }
                printf("%d\n",n);
            }
        }
    }
    return 0;
}

C- Robot Breakout
题意:给出一个坐标系中的一些点,给出了这些点所能移动的方向,判断这些点能否移动到同一个点上,能的话输出一个就行。
其实很简单,初步确定点可以存在范围为整个平面上,对每个点的四个方向进行判断,如果不能向哪个方向移动则更新点可能出现的的范围就行。

 #include<stdio.h>
    int main(){
    int q;
    scanf("%d",&q);
    while(q--){
    int n;
    scanf("%d",&n);
    int maxx=100000,maxy=100000;
    int minx=-100000,miny=-100000;
    for(int i=0;i<n;i++){
        int x,y,a,b,c,d;
       scanf("%d %d %d %d %d %d",&x,&y,&a,&b,&c,&d);
       if(!a&&x>minx) //4个方向分别判断
         minx=x;
         if(!b&&y<maxy) 
           maxy=y;
         if(!c&&x<maxx)
          maxx=x;
            if(!d&&y>miny)
          miny=y; 
    }
     if(maxx<minx||maxy<miny) {//这是不存在的情况
        printf("0\n");
        continue ;
     }
     else {//直接输出最小的情况
        printf("1 %d %d\n",minx,miny);
        continue ;
     }
    }
    return 0;
    }

D1- RGB Substring (easy version)
D2- RGB Substring (hard version)
题意:这两道题题意都一样,不同的只有数据范围。
要求是在一串只有R,G,B三个字符的字符串中找出长度是k的子串在对某些位做出变化后后得到的字符串是“RGBRGB…………” 的子串。题目要求最少的变化的位数。
我的想法是,最后得到长度为K子串可能从RGB,GBR,BRG这三种开头开始循环,如果,而如果对原字符串从开头对这三种顺序进行模拟,则所有的情况都可以包括其中,其中任意一位是R,G,B可能性都覆盖了。 对三种情况分别枚举,作前缀和数组,分别遍历一次,找出最小的改变次数即可。
超时了两次,第一次把memset换成for 快了点,仔细看才发现数组开小了,改了就过了。

#include<stdio.h>
#include<string.h>
int main(){
    int sum1[200100],sum2[200100],sum3[200100];
    int q;
    scanf("%d",&q);
    while(q--){
        char s[200010];
        int n,k;
        scanf("%d %d",&n,&k);
       for(int i=1;i<=n;i++) scanf(" %c",&s[i]);
        for(int i=0;i<=n;i++){
            sum1[i]=0;
            sum2[i]=0;
            sum3[i]=0;
        }
        sum1[0]=0,sum2[0]=0,sum3[0]=0;
        for(int i=1;i<=n;i++){
            if(i%3==0)
                 if(s[i]!='R') sum1[i]=sum1[i-1]+1;
                 else  sum1[i]=sum1[i-1]; 
             else if(i%3==1)
                   if(s[i]!='G') sum1[i]=sum1[i-1]+1;
                   else  sum1[i]=sum1[i-1];
               else 
                if(s[i]!='B') sum1[i]=sum1[i-1]+1;
                else  sum1[i]=sum1[i-1];
           }
for(int i=1;i<=n;i++){
    if(i%3==0)
            if(s[i]!='G') sum2[i]=sum2[i-1]+1;
            else  sum2[i]=sum2[i-1];
    else if(i%3==1)
       if(s[i]!='B') sum2[i]=sum2[i-1]+1;
       else  sum2[i]=sum2[i-1];
    else 
      if(s[i]!='R') sum2[i]=sum2[i-1]+1;
      else  sum2[i]=sum2[i-1];
}
 
for(int i=1;i<=n;i++){
    if(i%3==0)
          if(s[i]!='B') sum3[i]=sum3[i-1]+1;
          else  sum3[i]=sum3[i-1];
    else if(i%3==1)
       if(s[i]!='R') sum3[i]=sum3[i-1]+1;
       else  sum3[i]=sum3[i-1];
    else 
      if(s[i]!='G') sum3[i]=sum3[i-1]+1;
      else  sum3[i]=sum3[i-1];
}
      int min1=200000;
          for(int i=k;i<=n;i++){ /*三个前缀和数组分别遍历,找出长度为k的区间中最小那个*/
               if(sum1[i]-sum1[i-k]<min1)  min1=sum1[i]-sum1[i-k];
               if(sum2[i]-sum2[i-k]<min1)  min1=sum2[i]-sum2[i-k];
               if(sum3[i]-sum3[i-k]<min1)  min1=sum3[i]-sum3[i-k];
          }
          printf("%d\n",min1);
    }
    return 0;
} 

E,F留待后补

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • http://acm.hdu.edu.cn/showproblem.php?pid=1525 题意:给你两个数,每...
    Gitfan阅读 4,599评论 0 0
  • 第一章数和数的运算 一概念 (一)整数 1整数的意义 自然数和0都是整数。 2自然数 我们在数物体的时候,用来表示...
    meychang阅读 7,706评论 0 5
  • A. Restoring Three Numbers 题意 给出四个数:a+b、a+c、b+c、a+b+c,要求输...
    阿臻同学阅读 3,365评论 0 0
  • 题目链接难度: 中等 类型:动态规划 亚历克斯和李用几堆石子在做游戏。偶数堆石子排成一行,每堆都...
    wzNote阅读 12,253评论 0 1
  • “倾城,过来。”外婆相当严肃的招呼着她。倾城仿佛也被外婆的严肃感染了,慢慢走向外婆。“是时候让你知道一些事了。我知...
    你是我的原罪阅读 1,526评论 3 1

友情链接更多精彩内容