Codeforces Round #215 (Div. 2) or (Div. 1)

来源:互联网 发布:有卖淘宝账号的吗 编辑:程序博客网 时间:2024/05/22 13:35

A. Sereja and Coat Rack

题目:http://codeforces.com/contest/368/problem/A

题意:主人准备有n个衣架,每个衣架能出租对应的价格。一天聚会,来了m个人,需要给每个人一个衣架,收益为衣架的出租价格,如果没有衣架了,就得赔给客人d元钱。求最大收益。

思路:要计算最大收益,先把衣架价格按高低排序,贪心的办法先出租贵的衣架,如果衣架不够在计算需要扣除多少钱。

int a[150];int main(){    int i,j,k,d,n,m,summ=0;    scanf("%d%d",&n,&d);    for(i=0;i<n;++i)scanf("%d",&a[i]);    sort(a,a+n);    scanf("%d",&m);    for(i=0;i<n&&i<m;++i)summ+=a[i];    if(i==n)summ-=d*(m-n);    printf("%d",summ);    return 0;}


B. Sereja and Suffixes

题目:http://codeforces.com/contest/368/problem/B

题意:给n个整数组成的数组a,再给m个询问,每次询问是一个数l,计算a数组中第l个数开始到a数组结束,共有多少个不同的数值。

思路:先离线去计算所有可能的l值对应的结果,从a数组末尾开始往前推,计算不同的数的个数,因为数据范围不大,直接hash用b数组去记录当前状态出现过的数,如果是没出现过的数,修改b的值并增加计数。

int a[100050],b[100050],summ[100050];int main(){    int i,j,k,n,m;    scanf("%d%d",&n,&m);    for(i=0;i<n;++i)scanf("%d",&a[i]);    summ[n]=0;    for(i=n-1;i>=0;--i)    {        summ[i]=summ[i+1];        if(b[a[i]]==0)        {            b[a[i]]=1;            summ[i]++;        }    }    for(i=0;i<m;++i)    {        if(i)printf("\n");        int temp;        scanf("%d",&temp);        printf("%d",summ[temp-1]);    }    return 0;}


C. Sereja and Algorithm

题目:http://codeforces.com/contest/368/problem/C

题意:有一个字符串,只由xyz字符组成。给m个询问,每个询问限定一个子串,该字符串可以任意顺序排列,如果存在一个排列,其中所有三个字符大小的子串都是由"zyx", "xzy", "yxz"中的一个字符串组成的,则返回“”YES“,否则返回”NO“,如果字符串不足三个,返回”YES“。

思路:其实就是统计子串中x,y,z的个数,符合要求的情况下,x,y,z个数中,最大的个数和最小的差不会超过一个。

int x[100050],y[100050],z[100050];char str[100050];int main(){    scanf("%s",str);    memset(x,0,sizeof(x));    memset(y,0,sizeof(y));    memset(z,0,sizeof(z));    int i,j,len=strlen(str),m;    x[0]=y[0]=z[0]=0;    for(i=1;i<=len;++i)    {        x[i]=x[i-1];        y[i]=y[i-1];        z[i]=z[i-1];        if(str[i-1]=='x')x[i]++;        else if(str[i-1]=='y')y[i]++;        else if(str[i-1]=='z')z[i]++;    }    scanf("%d",&m);    for(i=0;i<m;++i)    {        int l,r,dx,dy,dz;        scanf("%d%d",&l,&r);        if(r-l<2)        {            printf("YES\n");            continue;        }        dx=x[r]-x[l-1];        dy=y[r]-y[l-1];        dz=z[r]-z[l-1];        //printf("%d %d %d\n",abs(dx-dz),abs(dx-dy),abs(dy-dz));        if(abs(dx-dz)<=1&&abs(dx-dy)<=1&&abs(dy-dz)<=1)printf("YES\n");        else printf("NO\n");    }    return 0;}

D. Sereja ans Anagrams

题目:http://codeforces.com/contest/368/problem/D

题意:给两个数组a和b,找出a中所有可能的q (q + (m - 1)·p ≤ n; q ≥ 1),使得序列aq, aq + p, aq + 2p, ..., aq + (m - 1)p,能够由数组b改变值的顺序排列而成。

思路:用temp记录b中每个数值能够使用的次数,当存在满足的情况时,temp中所有的数值都正好使用完,因为a数组的长度可能大于一次长度为m的序列遍历,所以之后的情况需要减掉序列最前面的一个值的使用,加上序列之后新增加的值,并记录当前状态的满足情况。最后把结果res数组按从小到大排序后输出。
int a[200050],b[200050];int main(){    int n, m, p, i, j, k;    vector <int> res;    scanf("%d %d %d", &n, &m, &p);    for (i=0;i<n;i++) scanf("%d",&a[i]);    for (i=0;i<m;i++) scanf("%d",&b[i]);    for (i=0;i<p && i+(ll)(m-1)*p<n; i++)    {        map<int,int>temp;        for(j=0;j<m;j++)temp[b[j]]++;        for(j=0,k=i;j<m;j++,k+= p)        {            temp[a[k]]--;            if (temp[a[k]]==0)temp.erase(a[k]);        }        for(j=i;;j+=p,k+=p)        {            if(temp.size()==0)res.push_back(j+1);            if(k>=n)break;            temp[a[k]]--;            if(temp[a[k]]==0) temp.erase(a[k]);            temp[a[j]]++;            if(temp[a[j]]==0) temp.erase(a[j]);        }    }    sort(res.begin(), res.end());    printf("%d\n", res.size());    for(i=0;i<res.size();i++)    {        if(i)printf(" ");        printf("%d", res[i]);    }    return 0;}
E. Sereja and the Arrangement of Numbers

题目:http://codeforces.com/contest/368/problem/E

题意:构造一个数组长度为n,使得数组中任意两个不同的值都至少相邻一次,每个不同的数都有对应的价值,得到数的价值就能无限使用对应的数,问满足题目的要求,能够得到的最大价值是多少。

思路:其实就是欧拉回路的问题,有n条边的长度能走,是否能把k个点构造的完全图所有边一遍走完,并找到k的最大值。由于奇数和偶数个点是的欧拉回路长度次数不同,分开计算。因为所需边长严格递增,为了减小复杂度k值的计算用二分处理。

typedef long long ll;int w[100050];int cal(int i){    int summ=(i-1)*i/2;    if(i&1)return summ+1;    else return summ+i/2;}int main(){    int n, m, p, i, j, k;    scanf("%d%d",&n,&m);    for(i=0;i<m;++i)scanf("%*d%d",&w[i]);    sort(w,w+m);    reverse(w,w+m);    int l=0,r=10000,mid;    while(l+1<r)    {        mid=l+(r-l)/2;        if(cal(mid)>n)r=mid;        else l=mid;    }    ll res=0;    for(i=0;i<min(l,m);++i)res+=w[i];    printf("%I64d",res);    return 0;}



原创粉丝点击