Codeforces Round #135 (Div. 2)

Codeforces Round #135 (Div. 2)  http://codeforces.com/contest/219


cf 再次悲剧了……11:30 开始,寝室早就断电了,只能靠笔记本电池艰难地维持那么一个多小时,而且没有灯,也不能再草稿纸上演算真心累呀……结果这次cf只A了前两个题目结尾,而且其中有个题目还不是1A,可怜……

 

A k-String
  水题,随便yy下就行了,当每个字符出现的次数都是k的倍数的时候存在满足条件的字符串
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

typedef long long ll;
char s[1010];
int cnt[100];

int main()
{
     int k;
     while(cin>>k>>s)
     {
         int len=strlen(s);
         for(int i=0;i<len;i++)
           cnt[s[i]-'a']++;
         bool ok=1;
         for(int i=0;i<26&&ok;i++)
            if(cnt[i]%k!=0) ok=0;
         if(ok)
         {
             string s="";
            for(int i=0;i<26;i++)
               if(cnt[i])
               {
                   for(int j=0;j<cnt[i]/k;j++)
                     s+=(char)('a'+i);
               }
             while(k--)
              cout<<s;
             cout<<endl;
         }
         else puts("-1");
     }
     return 0;
}

B
Special Offer! Super Price 999 Bourles
 这个题目还是比较有意思的题目,要多想会儿。 
题意: 给出  p 和  d ,要求 [ p-d , p] 这个区间范围内找包含末尾包含9的个数最多的数,如果多个数满足条件那么就找最大的那
思路:  我是枚举要找的末尾9的个数,然后再贪心找离p最近的数(这样的数只有一个),取最后值即可
个。
#include <iostream>
#include <cstdio>

using namespace std;

typedef long long ll;

int main()
{
     ll a,b;
     while(cin>>a>>b)
     {
         ll cnt=0,ans=0,d=a;
         while(d) cnt++,d/=10;
         for(ll i=1,x=10;i<=cnt;i++,x*=10)
         {
             if(x-1>a) break;
             ll rest=a%x,dd=a/x;
             ll tmp;
             if(rest==x-1) tmp=dd*x+x-1;
             else tmp=(dd-1)*x+x-1;
             if(tmp<a-b) break;
             ans=tmp;
         }
         if(ans) cout<<ans<<endl;
         else cout<<a<<endl;
     }
     return 0;
}

C
Color Stripe
这个题题意都不讲了,比赛的时候就是卡在这个题目上了,贪心dp都可以
dp做法:dp[ len [k ] 表示 把第len个数涂成k眼色前len块满足条件的最优解,即最少图的次数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
#define maxn 500010
#define inf 0x3fffffff
char s[maxn];
int n,k,dp[maxn][26];

void dfs(int id,int d,int pre)
{
    if(id<0) return;
    for(int i=0;i<k;i++)
      if(dp[id][i]==d&&i!=pre)
      {
          dfs(id-1,d- (i!=s[id]),i);
          putchar(i+'A');
          break;
      }
}
int main()
{
    while(scanf("%d%d",&n,&k)==2)
    {
        scanf("%s",s);

        for(int i=0;i<n;i++) s[i]-='A';
        for(int i=1;i<n;i++)
        for(int j=0;j<k;j++) dp[i][j]=inf;

        for(int j=0;j<k;j++) dp[0][j]= (j!=s[0]);
        for(int i=1;i<n;i++)
        for(int j=0;j<k;j++)
        for(int r=0;r<k;r++)
           if(j!=r) dp[i][j]=min(dp[i][j],dp[i-1][r]+(s[i]!=j));

        int Min=dp[n-1][0];
        for(int i=1;i<k;i++) Min=min(Min,dp[n-1][i]);
        printf("%d\n",Min);

       /* for(int i=0;i<n;i++)
        {
            for(int j=0;j<k;j++)
              cout<<dp[i][j]<<" ";
            cout<<endl;
        }*/
        dfs(n-1,Min,-1);
        puts("");
    }
    return 0;
}

贪心做法 , 不过我确实不怎么会证明为什么这样做就会ac,是我自己瞎yy出来的,贪心做法要快很多

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

typedef long long ll;
const int inf=0x3fffffff;
char s[500010];
int dp[500010][30];
int len,k;

void change(char &cc,char a,char b)
{
   for(int i=0;i<k;i++)
      if(i+'A'!=a&&i+'A'!=b) { cc=i+'A';break; }
}
int main()
{
    while(scanf("%d%d",&len,&k)==2)
    {
        scanf("%s",s);
        int t=0;
        if(k==2)
        {
            int t1=0,t2=0;
            for(int i=0;i<len;i++)
               if(s[i]!=i%2+'A') t1++;
            for(int i=0;i<len;i++)
               if(s[i]!=(i+1)%2+'A') t2++;
            if(t1>t2){
                printf("%d\n",t2);
                for(int i=0;i<len;i++) putchar((i+1)%2+'A');
                puts("");
            }else{
                printf("%d\n",t1);
                for(int i=0;i<len;i++) putchar(i%2+'A');
                puts("");
            }
            continue;
        }
        for(int i=0;i<len;i++)
          if(i+1<len&&s[i]==s[i+1])
            t++,change(s[i+1],s[i],s[i+2]);
        printf("%d\n%s\n",t,s);
    }
    return 0;
}

E
Parking Lot
如果做个跟这个类似的题目的话,直接就是水题了,两次dfs 即可,还有没有太坑爹没有爆栈
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
const int maxn=500010;
int dp[maxn];
vector<pair<int,bool> > g[maxn];
vector<int> ans;
int Min1(int &a,int b)
{
    if(a>b)
    {
        a=b;return 1;
    }
    return 0;
}
void dfs(int u,int fa)
{
    int sz=g[u].size();
    for(int i=0;i<sz;i++)
    {
        int v=g[u][i].first;
        bool ok=g[u][i].second;
        if(v==fa) continue;
        dfs(v,u);
        dp[u]+=dp[v]+ok;
    }
}
void dfs1(int u,int fa)
{
    int sz=g[u].size();
    for(int i=0;i<sz;i++)
    {
        int v=g[u][i].first;
        bool ok=g[u][i].second;
        if(v==fa) continue;
        dp[v]=dp[u]+ (ok?-1:1);
        dfs1(v,u);
    }
}
int main()
{
    int n,a,b;
    while(scanf("%d",&n)==1)
    {
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&a,&b);
            g[a].push_back(make_pair(b,0));
            g[b].push_back(make_pair(a,1));
        }
        memset(dp,0,sizeof(dp));
        dfs(1,-1);
        dfs1(1,-1);
        int Min=dp[1];
        for(int i=1;i<=n;i++)
          Min1(Min,dp[i]),g[i].clear();
        for(int i=1;i<=n;i++)
          if(Min==dp[i]) ans.push_back(i);
        printf("%d\n%d",Min,ans[0]);
        for(int i=1;i<ans.size();i++)
          printf(" %d",ans[i]);
        puts("");
        ans.clear();
    }
    return 0;
}

E
Parking Lot
 线段树的区间和并,蛋疼,调试了我好长时间,不知道wa了多少次,太弱了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 200010
int lsum[maxn<<2],msum[maxn<<2],rsum[maxn<<2],ans[1000001];
void pushup(int rt,int l)
{
    lsum[rt]=lsum[rt<<1];
    if(lsum[rt<<1]==l-l/2) lsum[rt]+=lsum[rt<<1|1];
    rsum[rt]=rsum[rt<<1|1];
    if(rsum[rt<<1|1]==l/2) rsum[rt]+=rsum[rt<<1];
    msum[rt]=max(max(msum[rt<<1],msum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]);
}
void build(int l,int r,int rt)
{
    lsum[rt]=msum[rt]=rsum[rt]=r-l+1;
    if(l==r) return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
void update(int p,int val,int l,int r,int rt)
{
    if(l==r)
    {
        lsum[rt]=msum[rt]=rsum[rt]=val;
        return;
    }
    int m=(l+r)>>1;
    if(p<=m) update(p,val,lson);
    else update(p,val,rson);
    pushup(rt,r-l+1);
}
int query(int p,int l,int r,int rt)
{
    if(l==r) return l;
    int m=(l+r)>>1;
    if(msum[rt<<1]>=p) return query(p,lson);
    else if(rsum[rt<<1]+lsum[rt<<1|1]>=p) return query(p-rsum[rt<<1],rson);
    else return query(p,rson);
}
int main()
{
    int n,m,id,a;
    while(scanf("%d%d",&n,&m)==2)
    {
        build(1,n,1);
       // update(6,0,1,n,1);
        while(m--)
        {
            scanf("%d%d",&id,&a);
            if(id==1)
            {
                int Max=max(lsum[1],max((msum[1]+1)/2,rsum[1])),np;
                if(Max==lsum[1]) np=1;
                else if((msum[1]+1)/2==Max)
                {
                    if(msum[1]%2==0)
                       np=query(msum[1]-1,1,n,1)-msum[1]/2+1;
                    else np=query(msum[1],1,n,1)-msum[1]/2;
                }else np=n;

                update(np,0,1,n,1);
                printf("%d\n",np);
                ans[a]=np;
            }
            else update(ans[a],1,1,n,1);
        }
    }
    return 0;
}



你可能感兴趣的:(Codeforces Round #135 (Div. 2))