codeforces-round501-div3

29 篇文章 0 订阅
11 篇文章 0 订阅

A.Points in Segments

这里写图片描述
这里写图片描述

题目大意:

给你n个小区间和最大边界m,这n个区间分布在1-m的大数轴区间上,请你输出这个数轴上不属于任何小区间的数的数目和本身。

解题思路:

将输入的区间遍历对区间内的数字进行唯一标记并统计数量sum,则未在任何小区间的数字数目就是m-sum,最后遍历大区间,未被标记的就是不在任何小区间的数了。
代码如下:

#include<iostream>
using namespace std;
int book[110];
int main()
{
  int n,m,sum=0;
  cin>>n>>m;
  for(int i=1;i<=n;i++)
  {
    int a,b;
    cin>>a>>b;
    for(int i=a;i<=b;i++)
    {
      if(book[i]==0)sum++;
      book[i]=1;
    }
  }
  cout<<m-sum<<endl;
  for(int i=1;i<=m;i++)
  {
    if(book[i]==0)cout<<i<<' ';
  }
  cout<<endl;
  return 0;
}

B. Obtaining the String

这里写图片描述
这里写图片描述

题目大意:

给定两个字符串s和t,问s能否通过有限次(10^4)相邻元素交换位置得到字符串t。如果能,输出交换次数和每次交换中交换对象前者的编号,否则输出-1。

解题思路:

首先用标记数组判断两个字符串组成元素种类和数量是否相同。不相同则输出-1,否则就开始移动。首先遍历字符串s,找到不相同的地方后从这个地方出发找本应该放在这里的字符在s中所在的位置,然后逐渐进行相邻元素交换直到对于元素归位,并保存交换前者编号和统计交换次数。
代码如下:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int main()
{
  string s,t;
  int n,a[26]={0},b[26]={0};
  int sum=0,result[10010]={0},k=0,cur=0,count=0;
  cin>>n;
  cin>>s>>t;
  for(int i=0;i<n;i++)//两个字符串包含字符书数量和种类是否相同
  {
    int k1=s[i]-'a',k2=t[i]-'a';
    a[k1]++;b[k2]++;
  }
  int flag=true;
  for(int i=0;i<26;i++)
  {
    if(a[i]!=b[i])
    {
      flag=false;
      break;
    }
  }
  if(!flag)cout<<-1<<endl;//不相同
  else if(s==t)cout<<0<<endl;//两串相等
  else
  {
    for(int i=0;i<n;i++)//遍历
    {
      if(s[i]==t[i])continue;//相同直接跳过
      for(int j=i+1;j<n;j++)//找t[i]在s中的对应位置并移动
      {
        if(s[j]==t[i])
        {
          k=j;//记录位置
          break;
        }
      }
    while(s[i]!=t[i])//移动
    {
      count++;//统计移动次数
      if(count>1e+4)
      {
        cout<<-1<<endl;
        return 0;
      }
      result[cur++]=k;//保存移动编号,记录路径
      swap(s[k],s[k-1]);//交换
      k--;
    }
  }
  cout<<cur<<endl;
  for(int i=0;i<cur;i++)cout<<result[i]<<' ';
 }
}

C.Songs Compression

这里写图片描述
这里写图片描述

题目大意:

有n首歌,每一首歌本身占据内存为a,可以压缩至b,现在给一个总内存m,问是否可以将所有的歌都保存下来,是的话最少压缩多少首歌?否就输出-1。

解题思路:

贪心,按照每首歌压缩空间从大到小排个序,先压缩大的。需要注意的存在不需要压缩也可以的情况,最少数就是0,这里没注意吃了一个WA。
代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct songs
{
  long long len1,len2,len3;
}s[100010];
int cmp(songs a,songs b)
{
  return a.len3>b.len3;
}
int main()
{
  long long n,m,sum1=0,sum2=0;
  cin>>n>>m;
  for(int i=0;i<n;i++)
  {
    cin>>s[i].len1>>s[i].len2;
    sum1+=s[i].len2;sum2+=s[i].len1;
    s[i].len3=s[i].len1-s[i].len2;
  }
  if(sum1>m) cout<<-1<<endl;
  else if(sum1==m)cout<<n<<endl;
  else
  {
    sort(s,s+n,cmp);
    long long sum3=0,i=0;
    while(sum2>m)
    {
      sum2-=s[i].len3;
      sum3++;
      i++;
    }
    cout<<sum3<<endl;
  }
  return 0;
}

D.Walking Between Houses

这里写图片描述
这里写图片描述

题目大意:

有n个线性分布的房子,初始时刻站在1号房子,要求是否能在移动k步时移动距离达到s,是则输出YES和路径,即访问过的房子编号(可来回访问,不能原地不动),否则输出NO。

解题思路:

这个题自己没写出来,一开始想了大爆搜,DP感觉都不行。后来补题时候发现有一些贪心思想,这个题难处在于方法很多,同一种情况对于很多种答案,我这里相当于是一个模拟吧,维护一个当前所在房子编号的变量,计算当前步下移动的距离,如果当前剩余距离大于n-1,那一步就走n-1,否则先走n-k(k是剩下的步数)然后每步只移动1格,总结起来就是move=min(s-k,n-1);
代码如下:

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
  long long n,k,s;
  cin>>n>>k>>s;
  if(k>s||k*(n-1)<s)cout<<"NO"<<endl;//
  else
  {
    cout<<"YES"<<endl;
    long long house=1;
    while(k--)
    {
      long long move=min(s-k,n-1);
      s-=move;
      if(house+move>n){house-=move;cout<<house<<' ';}
      else{house+=move;cout<<house<<' ';}
    }
  }
  return 0;
}

E1.Stars Drawing (Easy Edition)

这里写图片描述
这里写图片描述
这里写图片描述

题目大意:

给定一个图,能否用题目中规定的不同型的星图(size 1,size 2……)做出这个图,关注重点是*号,.可忽略。如果可以,输出该型星图中心星所在位置以及这个图的大小(也就是size),否则输出-1。注意必须将样例中的每一个*都能画出来。

解题思路:

我只会模拟的写法,需要注意标记每一个星图在样例中所占据的星,还要注意全是.的情况,代码如下:

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
char grid[110][110];//储存样例
int book[110][110];//标记*
struct result
{
  int row,colume,central;//行列,中心
}a[11000];
int main()
{
  int row,colume;
  cin>>row>>colume;
  for(int i=1;i<=row;i++)
  {
    for(int j=1;j<=colume;j++)
      cin>>grid[i][j];
  }
  int count=0,flag1=0;
  for(int i=2;i<=row-1;i++)
  {
    for(int j=2;j<=colume-1;j++)
    {
      if(grid[i][j]=='*')
      {
        flag1=1;//对于全是.情况的特判
      int top=0,bottom=0,l=0,r=0;
      int k1=i,k2=i,k3=j,k4=j;//开始找以当前为中心的星图大小
      while(grid[i][++k3]=='*')top++;
      while(grid[i][--k4]=='*')bottom++;
      while(grid[++k1][j]=='*')r++;
      while(grid[--k2][j]=='*')l++;
      int p=min(min(top,bottom),min(r,l));//星图size
      int t1=i,t2=i,t3=j,t4=j;
      if(p)//开始标记
      {
        book[i][j]=1;
        int t1=i,t2=i,t3=j,t4=j;
        while(t3<j+p)book[i][++t3]=1;
        while(t4>j-p)book[i][--t4]=1;
        while(t2>i-p)book[--t2][j]=1;
        while(t1<i+p)book[++t1][j]=1;
        count++;
        a[count].row=i;a[count].colume=j;a[count].central=p;//记录这个图
      }
    }
    }
  }
  bool flag=true;
  for(int i=1;i<=row;i++)
  {
    for(int j=1;j<=colume;j++)
    {
      if(grid[i][j]=='*')
      {
        if(book[i][j]==0)//有存在未被占据的*,则无法画出
        {
          i=row;
          flag=false;
          break;
        }
      }
    }
  }
  if(!flag1)cout<<0<<endl;//全是.
  else if(count&&flag)
  {
    cout<<count<<endl;
    for(int i=1;i<=count;i++)cout<<a[i].row<<' '<<a[i].colume<<' '<<a[i].central<<endl;
  }
  else cout<<-1<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值