Codeforces Round #401 (Div. 2)

来源:互联网 发布:邮箱的正则表达式的js 编辑:程序博客网 时间:2024/06/08 07:38

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