codeforces round#452 div2 解题记录

来源:互联网 发布:js touchevent事件 编辑:程序博客网 时间:2024/05/22 06:06
A - Splitting in Teams
题意

一串由1和2组成的序列,1表示1个可以任意组队的队员,2表示两个必须组在一个队的单元,问最多可以组成多少个队伍(每个队三个人)

思路

显然,三个人的队伍要不是1+2,要不就是1+1+1.因为要求队伍数量尽可能的多,所以要优先1+2,剩下的再1+1+1即可

代码(AC)
#include <iostream>using namespace std;int main(){    int n,a=0,b=0,m;    cin>>n;    while(n--)    {        cin>>m;        if(m==1)            a++;        else            b++;        }    m = a<b?a:b;    a -= m;    b -= m;    m += a/3;    cout<<m<<endl;    return 0;}
B - Months and Years
题意

给出一个长度为[1,24]的序列,元素为28,29,30或者31,表示某个月份的天数,问这个序列是否符合是几个连续月份的天数

思路

因为序列最长24,所以最多跨两年,考虑到闰年的情况,两年可以是平年+闰年,闰年+平年,平年+平年三种情况,所以我直接把四年(其中1,2,4是平年,3是闰年)的每月天数做成了个长度为12*4=48的数组,如果读取的序列是这个数组的子序列,则满足题意,否则则不满足。我觉得这个思路应该没问题啊。。然而WA,回头再想想

更新

知道错哪里了,因为24个月其实是可以覆盖三年的。。所以48是不够的。。改成72就好了。。

代码(AC)
#include <iostream>using namespace std;int t[12] = {31,28,31,30,31,30,31,31,30,31,30,31};int d[72];int in[24];int main(){    int i,j;    for(i=0;i<6;i++)    {        for(j=0;j<12;j++)        {            d[i*12+j] = t[j];        }    }    d[37] = 29;    int n;    cin>>n;    for(i=0;i<n;i++)        cin>>in[i];    for(i=0;i<72-n+1;i++)    {        for(j=0;j<n;j++)        {            if(d[i+j]!=in[j])                break;        }        if(j==n)            break;    }    if(i==72-n+1)        cout<<"no"<<endl;    else        cout<<"yes"<<endl;    return 0;}
C - Dividing the numbers
题意

把1……n这n个数字分成非空的两组,尽量使两组的和之差尽可能的小,输出任意一种分组方法

思路

显然是有规律的。刚开始只是按自己想象的来,然后WA,后来写了个dfs穷举了1-30左右的最小差,才发现想错了。。我这个代码太难看了。。应该是有个很精简的规律,我这个分类太复杂了

代码(AC)
#include <iostream>#include <cstdlib>using namespace std;int minres = 1000;void dfs(int sum,int cur,int n){    if(cur==n+1)    {        int m = (1+n)*n/2;        if(sum!=0&&sum!=m)        {            if(abs(m-2*sum)<minres)                minres = abs(m-2*sum);        }    }    else    {        dfs(sum,cur+1,n);        dfs(sum+cur,cur+1,n);    }}int main(){    int n;    cin>>n;    if(n%2==0)    {        int t = (n/2)%2;        int m = (n/2)/2;        cout<<t<<endl;        cout<<n/2<<' ';        for(int i=0;i<n/2;i++)        {            if(i<m)            {                cout<<i*2+2<<' ';            }            else            {                cout<<i*2+1<<' ';            }        }    }    else    {        if(n%4==3)        {            cout<<0<<endl;            cout<<n/2+1<<' ';            cout<<1<<' ';            int m = n/4;            for(int i=0;i<n/2;i++)            {                if(i<m)                {                    cout<<i*2+2+1<<' ';                }                else                    cout<<i*2+2<<' ';            }        }        else        {            cout<<1<<endl;            cout<<n/2+1<<' ';            cout<<1<<' ';            for(int i=(n-1)/4+2;i<(n-1)/4+2+(n-1)/2;i++)                cout<<i<<' ';        }    }    //这个是我自己调试找规律时候写的部分    /*for(int i=3;i<=21;i+=2)    {        minres = 10000000;        dfs(0,1,i);        cout<<i<<' '<<minres<<endl;    }*/    return 0;}
D - Shovel Sale
题意

输入一个整数n,问在1-n范围内,有多少对数的和结尾的9是尽可能多的?(有点拗口)
比如n=50的时候,因为有一对49,50加起来为99,末尾有两个9,是所有可能组合里面最多的,所以就要输出有多少个组合的末尾有两个9,即“尽可能多的(我翻译的不准确)”

思路

并没有思路。。n的范围很大,显然是有规律的,估计是O(1)的算法。我写了个小穷举,显示穷举了n和9的最大数量的关系,发现每到50,500,5000,9的最大数量就会+1.然后我有穷举了n和输出对数的关系,发现规律非常不明显,不会

代码(无,待补)
E - Segments Removal
题意

给定一个序列,按照指定方法,依次从左到右删除最长的连续重复元素,问要操作多少次才能清空序列

思路

瓶颈显然在于时间。数据量是20w,可以用数组存。我一开始设想是放数组里模拟,清空就放0,但是想了想这样子时间可能会很长。所以我打算用链表,顺便熟悉熟悉stl里的list。然而最后还是超时了。。应该有更好的算法的。我再想想

代码(TLE)
#include <iostream>#include <list>using namespace std;struct Node{    int d;    int c;};int main(){    ios::sync_with_stdio(false);    list<Node> l;    int n;    cin>>n;    int i;    int pre;    cin>>pre;    int cnt = 1;    for(i=0;i<n-1;i++)    {        int t;        cin>>t;        if(t==pre)        {            cnt++;        }        else        {            Node node;            node.d = pre;            node.c = cnt;            l.push_back(node);            pre = t;            cnt = 1;        }    }    Node node;    node.d = pre;    node.c = cnt;    l.push_back(node);    int ret = 0;    while(!l.empty())    {        ret++;        list<Node>::iterator iter,tmp,tmp2;        int m = 0;        for(iter=l.begin();iter!=l.end();iter++)        {            if(iter->c>m)                m = iter->c;        }        iter = l.begin();        while(iter->c!=m)            iter++;        tmp = iter;        tmp2 = iter;        tmp2--;        tmp++;        if(iter!=l.begin()&&tmp!=l.end()&&(tmp2->d==tmp->d))        {            l.erase(iter);            tmp2->c += tmp->c;            l.erase(tmp);        }        else            l.erase(iter);    }    cout<<ret<<endl;    return 0;}
F - Letters Removing
题意

输入一个长度为n的字符串,只有大小写字母和数字,做m次操作,每次操作为从l到r的闭区间中删去所有字符c,输出最后操作完毕的字符串

思路

由于有很多删除操作,所以打算用链表实现,使用了stl里面的list实现,然而,,,tle超时,下一步打算手写个单链表试试看看是不是stl的问题,还是这道题的关键点并不是链表

代码(TLE)
#include <iostream>#include <list>using namespace std;int main(){    ios::sync_with_stdio(false);    int n,m;    cin>>n>>m;    list<char> l;    int i,j;    list<char>::iterator iters,itere,tmp;    for(i=0;i<n;i++)    {        char t;        cin>>t;        l.push_back(t);    }    for(i=0;i<m;i++)    {        int le,r;        char c;        cin>>le>>r>>c;        iters = l.begin();        for(j=1;j<le;j++)            iters++;        itere = l.begin();        for(j=1;j<=r;j++)            itere++;        while(iters!=itere)        {            if(*iters==c)            {                tmp = iters;                iters++;                l.erase(tmp);            }            else                iters++;        }    }    for(itere=l.begin();itere!=l.end();++itere)        cout<<(*itere);    cout<<endl;    return 0;}
原创粉丝点击