• 题解Educational Codeforces Round 75 [Rated for Div. 2] (CF1251)


    今天开题一个半小时,只做了半小时写完了前三题。。T3还是最后1min交上去的。。不得不说我们小区维修导致我Rating狂降啊。。。或者说我太菜了(

    有看不懂的看看代码,也许有注释,如果没有注释可以研究一下代码(应该比较好懂),还看不懂就在底下留言或者私信我,我看到就会给予回复。

    A:看看某个字母有没有连续一段为奇数的,有说明可行。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define it register int
     4 #define il inline
     5 using namespace std;
     6 const int N=100005;
     7 int T,cn[N],n;
     8 char s[N];
     9 int main(){
    10     scanf("%d
    ",&T);
    11     while(T--){
    12         scanf("%s",s+1),n=strlen(s+1);
    13         for(it i=0;i<26;++i) cn[i]=0;
    14         for(it i=1,j,x;i<=n;i=j){
    15             j=i,x=0;
    16             for(;s[j]==s[i]&&j<=n;++j) ++x;
    17             if(x&1) cn[s[i]-'a']=1;
    18         }
    19         for(it i=0;i<26;++i) if(cn[i]) putchar(i+'a');
    20         putchar('
    ');
    21     }
    22     return 0;
    23 }
    View Code

    B:我们发现0和1可以随便摆放,于是DP,设f[i][j]表示前i个分配了j个1,可以获得的最大回文串。

    若k是奇数,且len[i]为奇数,可行;若k是偶数,无论len[i]为奇数偶数都可行。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define it register int
     4 #define il inline
     5 using namespace std;
     6 const int N=55;
     7 int T,n,a[N],o1,o2,f[N][N*N];
     8 char s[N][N];
     9 il int Max(it p,it q){
    10     return p>q?p:q;
    11 }
    12 il void ckMax(int &p,it q){
    13     p=(p>q?p:q);
    14 }
    15 int main(){
    16     scanf("%d
    ",&T);
    17     while(T--){
    18         scanf("%d
    ",&n),o1=0;
    19         for(it i=1;i<=n;++i)
    20             scanf("%s",s[i]+1),a[i]=strlen(s[i]+1);
    21         for(it i=1;i<=n;++i)
    22             for(it j=1;j<=a[i];++j) o1+=(s[i][j]=='1'),o2+=(s[i][j]=='0');
    23     //    f[i][j]:前i个分配了j个1
    24         memset(f,-1,sizeof(f));f[0][0]=0;
    25         for(it i=1;i<=n;++i)
    26             for(it j=0;j<=o1;++j)
    27                 for(it k=0;k<=a[i]&&k+j<=o1;++k)
    28                     if(~f[i-1][j]) ckMax(f[i][j+k],f[i-1][j]+((k&1)&&(a[i]&1))+(!(k&1)));
    29         printf("%d
    ",f[n][o1]);
    30     }
    31     return 0;
    32 }
    View Code

    C:显然奇数偶数的相对顺序不改变,把奇数偶数搞个数组记录下,然后归并排序。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define it register int
     4 #define il inline
     5 using namespace std;
     6 const int N=1000005;
     7 int T,a[N],pos[N],n,b[N],cna,cnb;
     8 char s[N];
     9 il void fr(int &num){
    10     num=0;char c=getchar();int p=1;
    11     while(c<'0'||c>'9') c=='-'?p=-1,c=getchar():c=getchar();
    12     while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar();
    13     num*=p;
    14 }
    15 int main(){
    16     fr(T);
    17     while(T--){
    18         scanf("%s",s+1);
    19         n=strlen(s+1);cna=cnb=0;
    20         for(it i=1,x;i<=n;++i) ((x=s[i]-'0')&1)?a[++cna]=x:b[++cnb]=x;
    21         it i=1,j=1;
    22         while(i<=cna&&j<=cnb)
    23             if(a[i]<b[j]) printf("%d",a[i]),++i;
    24             else printf("%d",b[j]),++j;
    25         while(i<=cna) printf("%d",a[i]),++i;
    26         while(j<=cnb) printf("%d",b[j]),++j;
    27         putchar('
    ');
    28     }
    29     return 0;
    30 }
    31 //所有的奇数和偶数相对位置不变 把奇数偶数搞个数组记录下
    View Code

    剩下三题是考后补的:

    D:一眼二分。。早知道先开D了(分多啊)二分一下最小的可行答案并且进行检验。一个小贪心,最开始按照l,r从大到小排序。很凉心地放D题。。

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #define it register int
     4 #define il inline 
     5 using namespace std;
     6 const int N=1000005;
     7 typedef long long ll;
     8 struct ky{
     9     ll a,b;
    10     bool operator<(const ky&p)const{
    11         return a^p.a?a>p.a:b>p.b;
    12     }
    13 }a[N];
    14 int T,n,half;
    15 ll m;
    16 il bool ck(ll x){
    17     ll cnt=0,tot=0;
    18     for(it i=1;i<=n;++i) a[i].a>=x?tot+=a[i].a,++cnt:(a[i].b<x?tot+=a[i].a:(cnt<half?++cnt,tot+=x:tot+=a[i].a));
    19     if(cnt<half) return 0;
    20     return tot<=m;
    21 }
    22 il void ms(){
    23     ll l=0,r=1e18,mid;
    24     while(l<=r) mid=l+r>>1,ck(mid)?l=mid+1:r=mid-1;
    25     printf("%I64d
    ",r);
    26 }
    27 namespace io {
    28     const int SIZE = (1 << 21) + 1;
    29     char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55];
    30     int f, qr;
    31 #define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
    32     inline void flush () {fwrite (obuf, 1, oS - obuf, stdout);oS = obuf;}
    33     template <class I>
    34     inline void fr (I &x) {
    35         for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
    36         for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15);
    37         x *= f;
    38     }
    39     struct Flusher_ {~Flusher_() {flush();}} io_flusher_;
    40 }
    41 using io :: fr;  
    42 int main(){ 
    43     fr(T);
    44     while(T--){
    45         fr(n),fr(m),half=(n+1>>1);
    46         for(it i=1;i<=n;++i) fr(a[i].a),fr(a[i].b);
    47         sort(a+1,a+1+n),ms();
    48     }
    49     return 0;    
    50 }
    View Code

    E:看到双倍经验直接看hard version 。。然后以为是个dp。。突然发现可以贪心。。然后就随手一发贪心。。过了之后看到标签还有binary search ,我并没有想到,如果有会二分做法的大佬请留言教我一下或私信D我,谢谢指教!

    更好玩的是交了easy version 之后看到tag是dp和greedy,并没有binary search,难道说hard version的算法不适用于easy version?幸好我打了贪心两边都能过

     1 #include<stdio.h>
     2 #include<vector>
     3 #include<queue>
     4 #include<algorithm>
     5 #define it register int
     6 #define il inline 
     7 using namespace std;
     8 const int N=1000005;
     9 int T,n; 
    10 vector<int> g[N];
    11 long long ans;
    12 il void fr(int &num){
    13     num=0;char c=getchar();int p=1;
    14     while(c<'0'||c>'9') c=='-'?p=-1,c=getchar():c=getchar();
    15     while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar();
    16     num*=p;
    17 }
    18 priority_queue<int,vector<int>,greater<int> > q;
    19 int main(){ 
    20     fr(T);
    21     while(T--){
    22         fr(n),ans=0;
    23         for(it i=1,x,y;i<=n;++i) fr(x),fr(y),g[x].push_back(y);//收买i要x人或者花y元
    24         for(it i=n-1;i>=0;--i){//注意到一个显而易见的事实就是人数不会超过n
    25             for(it j=0,sz=g[i].size();j<sz;++j) q.push(g[i][j]);
    26             while(q.size()>n-i) ans+=q.top(),q.pop();//选前n-i小的人进行收买
    27         }
    28         printf("%I64d
    ",ans);
    29         for(it i=0;i<n;++i) g[i].clear();while(!q.empty()) q.pop();//多测不清空 爆零两行泪
    30     }
    31     return 0;
    32 }
    View Code

    F:太迟了先咕着明早更。

    至少前五题赶在官方题解出来之前写完了自己的题解。。我还是太菜了,还要继续磨砺吖!

    有更好的做法欢迎留言哦~

    upd:请教了机房大佬发现F我不会。。那么就看似咕咕实则不会吧!(弃F坑)

    upd:机房大佬告诉我B有更好的O(n)做法:乱搞。(吊锤我的dp做法,还好我的程序时间复杂度比较稳……)

    首先可以证明要么有n个回文串要么有n-1个回文串,因为我们可以通过舍弃最多一个串使得剩下的都成立。

    然后就可以进行乱搞。我们可以记录一下有多少个奇数串,多少个偶数串。(这里的奇数偶数指的是长度)。如果有>1的奇数串答案肯定为n,如果只有一个奇数串答案肯定是n-1,如果全是偶数串,判断一下0和1的个数,如果都是奇数个答案就是n-1,否则答案为n。代码就不贴了(我也懒得写)。

    upd:机房大佬告诉我B题我的程序理论时间复杂度是O(n^5)。。但是极限数据只需要0.8s,肯定是跑不满的。。如果有知道我B题dp的实际时间复杂度的大佬请私信我或者在底下留言,谢谢!

  • 相关阅读:
    毕业生的商业软件开发之路 C#语言简介
    [毕业生的商业软件开发之路]第一次使用VS.NET集成开发环境
    一种应用程序命令执行架构设计
    DCWriter 电子病历文档编辑器的 电子病历功能规范对照表
    [毕业生的商业软件开发之路]积累与创新
    WEB开发人员的微软技术战略
    PureMVC(AS3)剖析:吐槽
    走在网页游戏开发的路上(九)
    [服务器开发]可伸缩系统的设计模式(译)
    回合制页游
  • 原文地址:https://www.cnblogs.com/Kylin-xy/p/11735955.html
Copyright © 2020-2023  润新知