Codeforces Round #401 (Div. 2)

Codeforces Round #401 (Div. 2)

A. Shell Game

题目链接:http://codeforces.com/contest/777/problem/A
题意:这个题的意思就是有三个帽子,将一个小球藏在一个帽子下面,进行n次变换,奇数次将左边帽子与中间交换,偶数次将右边帽子与中间交换,输入移动次数n和移动结束后球在哪里k,求最开始求放在了哪个帽子下面。
分析:可以通过简单列举n=1,2,3,4,5,6,7和k=0,1,2的情况可以发现,球的位置以六为周期存在规律,按规律倒推即可。

#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <string>
#include <set>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

int main()
{
    int n,x;
    cin>>n>>x;
    n=n%6;
    if(n==1)
    {
        if(x==0)
            cout<<"1"<<endl;
        else if(x==1)
            cout<<"0"<<endl;
        else
            cout<<"2"<<endl;
    }
    if(n==2)
    {
        if(x==0)
            cout<<"1"<<endl;
        else if(x==1)
            cout<<"2"<<endl;
        else
            cout<<"0"<<endl;
    }
    if(n==3)
    {
        if(x==0)
            cout<<"2"<<endl;
        else if(x==1)
            cout<<"1"<<endl;
        else
            cout<<"0"<<endl;
    }
    if(n==4)
    {
        if(x==0)
            cout<<"2"<<endl;
        else if(x==1)
            cout<<"0"<<endl;
        else
            cout<<"1"<<endl;
    }
    if(n==5)
    {
        if(x==0)
            cout<<"0"<<endl;
        else if(x==1)
            cout<<"2"<<endl;
        else
            cout<<"1"<<endl;
    }
    if(n==0)
    {
        if(x==0)
            cout<<"0"<<endl;
        else if(x==1)
            cout<<"1"<<endl;
        else
            cout<<"2"<<endl;
    }
    return 0;
}

B. Game of Credit Cards

题目链接:http://codeforces.com/contest/777/problem/B
题意:有两个人进行比赛,两个人分别有一串数字,每次拿出一个数字进行比较,数字较低的一方惩罚点数加一,如果相等,则惩罚点数不变。比赛时,Sherlock将按给定序列拿出数字,Moriary会按自己的方案拿出数字,问如何使得Moriarty得到最小的惩罚点数和如何使得Sherlock得到最多的惩罚点数。
分析:这个题的方案有点类似于田忌赛马的策略,首先对Moriary所拥有的数字进行由大到小排序,然后按Sherlock的顺序利用lower_bound函数对Moriarty进行查找,不同的是A问使用第一个大于等于数字即可,B问必须使用大于的数字才可以,然后用两个数组分别标记在A问条件下和B问条件下这个数字是否已经被使用。
给出代码:

#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <string>
#include <set>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
char num1[1010];
char num2[1010];
int d1[1010];
int d2[1010];
int main()
{
   int n;
   cin>>n;
   scanf("%s",num1);
   scanf("%s",num2);
   int sum1=n;
   int sum2=0;
   sort(num2,num2+n);
   for(int i=0;i<n;i++)
   {
       int t=lower_bound(num2,num2+n,num1[i])-num2;
       int mark1=0;
       int mark2=0;
       for(int j=t;j<n;j++)
       {
           if(num2[j]>=num1[i]&&d1[j]==0&&mark1==0)
           {
               d1[j]=1;
               sum1--;
               mark1=1;
           }
           if(num2[j]>num1[i]&&d2[j]==0&&mark2==0)
           {
               d2[j]=1;
               sum2++;
               mark2=1;
           }
           if(mark1&&mark2)
            break;
       }
   }
   cout<<sum1<<endl<<sum2<<endl;
   return 0;
}

C. Alyona and Spreadsheet

题目链接:http://codeforces.com/contest/777/problem/C
题意:
这个题的意思就是给出一个n*m的矩阵,进行k次查询,问在矩阵的所有列中,是否存在至少一列满足由a行到b行是非递减的。
题目分析:
原本这题我想要用二维数组存的,然后发现这样会内存超限,然后改用vector容器来存,这样就不会内存超限了。然后一开始是用3重for循环来查询是否满足条件,然后发现这样又会超时TAT,想了半天改成了二重for循环。第一重for循环是第几列,第二重for循环是第几行,用一个t表示起始位置,用一个一维数组表示范围,如
d[i]=t,表示由t到i是非递减的,当遇到不满足情况的时候,更新t的值。
给出代码:

#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>

using namespace std;
const int maxn=100100;
vector<int> num[maxn];
int n,m;
int d[100100];
int main()
{
     int b;
     cin>>n>>m;
     for(int i=0;i<n;i++)
     {
         d[i]=i;
         for(int j=0;j<m;j++)
         {
             scanf("%d",&b);
             num[i].push_back(b);
         }
     }
     for(int j=0;j<m;j++)
     {
         int t=0;
         for(int i=1;i<n;i++)
         {
            if(num[i][j]>=num[i-1][j]&&t<d[i])
                d[i]=t;
            else if(num[i][j]<num[i-1][j])
            {
                t=i;
            }
         }
     }
     int k;
     cin>>k;
     int x,y;
     for(int i=0;i<k;i++)
     {
         scanf("%d%d",&x,&y);
         x=x-1;
         y=y-1;
         if(d[y]<=x)
            printf("Yes\n");
         else
            printf("No\n");
     }
     return 0;
}

D. Cloud of Hashtags

题目链接:http://codeforces.com/contest/777/problem/D
题意:有N个标题,但这些标题不是按字典序排序的,为了变成字典序排序,可以从后往前删除字符,问最少删除多少个字符可以使得所有的标题为字典序。每个标题开头的‘#’不计入字典序排序范围也不可删掉,除此之外可以全部删掉。
题目分析:又是一个暴力的题目。可以从后面的标题往前面进行循环删除,这样删除以后不会影响后面的情况。然后利用string进行字符串的各种操作就可以了。
给出代码:

#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <string>
#include <set>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
vector<string> a;
int main()
{
    string b;
    int n;
    cin>>n;
    for(int i=0; i<n; i++)
    {
        cin>>b;
        a.push_back(b);
    }
    int t=a.size();
    for(int i=t-1; i>0; i--)
    {
        int x1=a[i].length();
        int x2=a[i-1].length();
        //int h=-1;
        if(a[i]<a[i-1])
        {
            int h=x1;
            for(int j=0; j<x1; j++)
            {
                if(a[i-1][j]>a[i][j])
                {
                    h=j;
                    break;
                }
            }
            string tep;
            for(int j=0; j<h; j++)
            {
                tep+=a[i-1][j];
            }
            a[i-1]=tep;
        }
    }
    for(int i=0; i<n; i++)
    {
        cout<<a[i]<<endl;
    }
    return 0;
}

E. Hanoi Factory

题目链接:http://codeforces.com/contest/777/problem/E
题意:
有n个圆环,圆环中空,给出圆环的内半径,外半径和高度,问如何利用这些圆环得到一个最高的塔。规则:下面的圆环的外半径必须大于上面圆环的外半径,上面圆环的外半径必须大于下面圆环的外半径。
分析:
一开始拿到这个题,还以为是个DP,因为前不久在紫书上做过一个类似的题目,但是写了半天写出来以后发现DP竟然会超时==,然后查了查题解发现是一个利用sort和stack进行的贪心0,0果然我脑洞不够大。(另外提一句,这个题我DP的思路是先按外半径从小到大排序后,d[i]表示以第I个为底的时候的高端,然后进行由0到i的循环,不断更新d[i]的值,

if(rings[j].a<=rings[i].a&&rings[i].b<rings[j].a)
        {
          //  cout<<"i="<<i<<" j="<<j<<" "<<d[i]<<" "<<d[j]+rings[i].h<<endl;
            d[i]=max(d[i],d[j]+rings[i].h);
        }

然后再更新maxn的值,可惜超时了,n有点大)
这个题的正确做法是将圆环按外半径由大到小,内半径由大到小排序后,利用栈模拟这个塔,如果这个圆环可以放到栈顶圆环上,那就入栈,如果不可以,就将栈中圆环出栈直到圆环可以放入为止,每次放入圆环都要更新max的值(这种贪心可行的原因是因为圆环都是有序的,出栈的圆盘在放入新圆盘后也是无法继续入栈的)
给出代码:

#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <string>
#include <set>
#include <cstdio>
#include <cmath>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;
//#define long long ll;
struct ring
{
    long long int a,b,h;
}rings[100010];
long long int d[100010];
bool cmp(const ring &x,const ring &y)
{
    if(x.a==y.a&&x.b==y.b)
        return x.h>y.h;
    else if(x.a!=y.a)
        return x.a>y.a;
    else
        return x.b>y.b;
}
stack<ring> mark;
int main()
{
  int n;
  cin>>n;
  for(int i=0;i<n;i++)
  {
      scanf("%lld%lld%lld",&rings[i].b,&rings[i].a,&rings[i].h);
  }
  sort(rings,rings+n,cmp);
 // for(int i=0;i<n;i++)
//    cout<<rings[i].a<<" "<<rings[i].b<<" "<<rings[i].h<<endl;
//  cout<<endl;
  long long int ans=rings[0].h;
  long long int sum=rings[0].h;
  mark.push(rings[0]);
  //cout<<sum<<" "<<ans<<endl;
  for(int i=1;i<n;i++)
  {
      while(!mark.empty()&&rings[i].a<=mark.top().b)
      {
          sum-=mark.top().h;
          mark.pop();
      }
      sum+=rings[i].h;
      mark.push(rings[i]);
      ans=max(ans,sum);
  }
  cout<<ans<<endl;
  return 0;
}

总结:

这一次的CF题目大多是一些暴力题目,最后一个题有点难,其他的就是靠自己的发挥了。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值