Codeforces Round #215 (Div. 2)

来源:互联网 发布:重生之星际淘宝主下载 编辑:程序博客网 时间:2024/05/21 15:03
A. Sereja and Coat Rack
题意:饭店有n个挂钩,顾客想挂衣服需要付ai卢布,顾客回旋花费最少的,如果没有空的,店主需要付给顾客d卢布,现在有m个顾客,问店主能挣多少钱
下面是代码:
#include<iostream>#include<algorithm>#include<cstdio>using namespace std;int a[110];int main(){    int n,d,m,ans=0;    cin>>n>>d;    for(int i=0;i<n;i++)    cin>>a[i];    cin>>m;    sort(a,a+n);    int len=min(m,n);    for(int i=0;i<len;i++)    ans+=a[i];    if(n<m)    ans-=d*(m-n);    cout<<ans<<endl;    return 0;}

B. Sereja and Suffixes
题意:给你n个数a1,a2...an,然后给你m个位置l1,l2...lm,输出从li开始到n有多少个不同的数
思路:从后往前预处理一下,用一个vis数组,看是否出想过,统计出从当前到最后有多少不同
#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int maxn=100010;bool vis[maxn];int a[maxn],cnt[maxn];int main(){    int n,m,x;    memset(vis,0,sizeof(vis));    memset(cnt,0,sizeof(cnt));    scanf("%d%d",&n,&m);    for(int i=1; i<=n; i++)        scanf("%d",&a[i]);    cnt[n]=1;    vis[a[n]]=1;    for(int i=n-1; i>=1; i--)        if(!vis[a[i]]) {cnt[i]=cnt[i+1]+1;vis[a[i]]=1;}        else cnt[i]=cnt[i+1];    while(m--)    {        scanf("%d",&x);        printf("%d\n",cnt[x]);    }    return 0;}

C. Sereja and Algorithm
题意:给你一个字符串,如果任意连续子串都是"xzy","yxz","zyx"这样的,则输出“YES”,如果存在,可以任意的打乱顺序,如果无论如何大乱,都不行,输出“NO”。
思路:这三种字符串,无论如何排序,都可以串起来,x,y,z的数量最多相差一,所以预处理一下,统计出区间上有多少个x,y,x,如果数量关系满足,则一定可以。
下面是代码:
#include<iostream>#include<cstring>#include<cstdio>#include<string>#include<cmath>using namespace std;const int maxn=100010;int cnt[5];char a[maxn];int x[maxn],y[maxn],z[maxn];int Abs(int x){    return x<0?(-x):x;}bool can(int x,int y,int z){    if(x==y&&(Abs(z-x)<=1))    return true;    return false;}int main(){    int n,l,r;    scanf("%s%d",a,&n);    int len=strlen(a);    x[0]=y[0]=z[0]=0;    for(int i=0;i<len;i++)    {        if(a[i]=='x') {x[i+1]=x[i]+1;y[i+1]=y[i];z[i+1]=z[i];}        else if(a[i]=='y'){y[i+1]=y[i]+1;x[i+1]=x[i];z[i+1]=z[i];}        else {z[i+1]=z[i]+1;x[i+1]=x[i];y[i+1]=y[i];}    }    while(n--)    {        scanf("%d%d",&l,&r);        if(r-l+1<3){printf("YES\n");continue;}        int numx=x[r]-x[l-1],numy=y[r]-y[l-1],numz=z[r]-z[l-1];        if(can(numx,numy,numz)||can(numx,numz,numy)||can(numy,numz,numx))        printf("YES\n");        else printf("NO\n");    }    return 0;}
D. Sereja ans Anagrams

题意:给两个数组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数组按从小到大排序后输出。
下面是代码
#include<iostream>#include<vector>#include<map>#include<algorithm>#include<cstdio>using namespace std;const int maxn=2*100010;int a[maxn],b[maxn];int main(){    int n,m,p,k,j;    cin>>n>>m>>p;    for(int i=1;i<=n;i++)        cin>>a[i];    for(int i=1;i<=m;i++)        cin>>b[i];    vector<int> ans;    for(int i=1;i<=p&&i+(long long)(m-1)*p<=n;i++)    {        map<int,int> tmp;        for(j=1;j<=m;j++) tmp[b[j]]++;        for(j=1,k=i;j<=m;j++,k+=p)        {            tmp[a[k]]--;            if(tmp[a[k]]==0) tmp.erase(a[k]);        }        for(j=i;;j+=p,k+=p)        {            if(tmp.size()==0) ans.push_back(j);            if(k>n) break;            tmp[a[k]]--;            if(tmp[a[k]]==0) tmp.erase(a[k]);            tmp[a[j]]++;            if(tmp[a[j]]==0) tmp.erase(a[j]);        }    }    bool first=true;    sort(ans.begin(),ans.end());    cout<<ans.size()<<endl;    for(int i=0;i<ans.size();i++)    if(first){cout<<ans[i];first=false;}    else cout<<' '<<ans[i];    cout<<endl;    return 0;}


E. Sereja and the Arrangement of Numbers(转载)

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

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

#include<cstdio>#include<iostream>#include<algorithm>using namespace std;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(){    //#ifndef ONLINE_JUDGE    //    freopen("in.txt","r",stdin);    //#endif    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;}




0 0
原创粉丝点击