Codeforces Round #215 (Div. 2)

u010660276發表於2014-01-12
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;
}




相關文章