Codeforce Round #545(Div2) (BCD题解)

B:

  给出n个元素,每个元素有两个属性(每个属性的取值为0或1),(n为偶数),即:一共有四种数对(0,0),(0,1),(1,0),(1,1)

  要求把n个元素分为2组,要求第一组的属性二的1的数量和第二组的属性二的1的数量相等( 设两组分别为A,B,满足即SUM(A.first==1)=SUM(B.second==1)

  ,求分组方案

  题解:

  一开始想用贪心来做,后来发现分情况分得不清楚了,然后看了下题解,发现题解是根据每组每种数对的数量的等量关系进行列方程,两个方程四个未知数,数据范围是(n<=5000),所以可用O(n^2)暴力枚举两个值然后求解

  代码如下:  

 1 #include<bits/stdc++.h>
 2 #define pii pair<int,int>
 3 using namespace std;
 4 const int maxn=5e3+5;
 5 struct node
 6 {
 7     int id,first,second;
 8 }art[maxn];
 9 int n;
10 map<pii,int>m;
11 bool cmp(node a,node b)
12 {
13     int sa=a.first+a.second,sb=b.first+b.second;
14     if(sa==1 && sb==1) return a.first<b.first;
15     return sa<sb;
16 }
17 int main()
18 {
19     cin>>n;string t,tt;cin>>t>>tt;
20     m[{0,1}]=0,m[{1,1}]=0,m[{1,0}]=0,m[{0,0}]=0;
21     for(int i=1;i<=n;++i)
22     {
23         art[i].first=t[i-1]-'0';
24         art[i].second=tt[i-1]-'0';
25         ++m[{art[i].first,art[i].second}];
26         art[i].id=i;
27     }
28     sort(art+1,art+1+n,cmp);
29     //cout<<endl;
30     static int s00,s11,s01,s10; s00=s11=s01=s10=-1;
31     for(int i=1;i<=n;++i)
32     {
33         if(s00<0 && art[i].first==0 && art[i].second==0) s00=i;
34         if(s01<0 && art[i].first==0 && art[i].second==1) s01=i;
35         if(s10<0 && art[i].first==1 && art[i].second==0) s10=i;
36         if(s11<0 && art[i].first==1 && art[i].second==1) s11=i;
37     }
38     int na=m[{0,0}],nb=m[{0,1}],nc=m[{1,0}],nd=m[{1,1}];
39     /*
40     for(int a=0;a<=na;++a)
41     {
42         for(int d=0;d<=nd;++d)
43         {
44             if(a-d==n/2-nd-nb)
45             {
46                 int b=(nb+nd-2*d)/2;      //最开始的时候枚举a,d求b,c   但是这里会出现一个问题,就是b=(......)/2,如果(......)是奇数,机会出现错误,所以换了枚举方式
47                 int c=n/2-a-b-d;
48                 if(b<0 || c<0 || b>nb || c>nc) continue;
49                 if(a)for(int i=s00,j=1;j<=a;++j,++i) cout<<art[i].id<<" ";
50                 if(b)for(int i=s01,j=1;j<=b;++j,++i) cout<<art[i].id<<" ";
51                 if(c)for(int i=s10,j=1;j<=c;++j,++i) cout<<art[i].id<<" ";
52                 if(d)for(int i=s11,j=1;j<=d;++j,++i) cout<<art[i].id<<" ";
53                 return 0;
54             }
55         }
56     }*/
57     for(int b=0;b<=nb;++b)
58     {
59         for(int d=0;d<=nd;++d)
60         {
61             int c=nb+nd-b-2*d;
62             int a=n/2-b-c-d;    //先把a,c算出来,再带入式子看看对不对,注意带进去的式子,不能是恒等式,如果是恒等式,肯定是错的(原因不赘述)
63                                 //其实不能说是错的,不过因为是恒等式所以肯定求不出来
64             if(a-d==n/2-nb-nd)
65             {
66                 if(a<0 || c<0 || a>na || c>nc) continue;
67                 if(a)for(int i=s00,j=1;j<=a;++j,++i) cout<<art[i].id<<" ";
68                 if(b)for(int i=s01,j=1;j<=b;++j,++i) cout<<art[i].id<<" ";
69                 if(c)for(int i=s10,j=1;j<=c;++j,++i) cout<<art[i].id<<" ";
70                 if(d)for(int i=s11,j=1;j<=d;++j,++i) cout<<art[i].id<<" ";
71                 return 0;
72             }
73         }
74     }
75     cout<<-1;return 0;
76 }

  C:

  坐标离散化,复习一下lower_bound和unique(可能因为我很菜233333)

  代码如下:

  

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+5;
int plat[maxn][maxn];
int row[maxn][maxn];
int col[maxn][maxn];
int row_end[maxn],col_end[maxn];
int n,m;

int main()
{
    ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=0;i<n;++i)
    {
        for(int j=0;j<m;++j)
        {
            cin>>plat[i][j];
            row[i][j]=plat[i][j];
            col[j][i]=plat[i][j];
        }
    }
    for(int i=0;i<n;++i)
    {
        sort(row[i],row[i]+m);
        row_end[i]=unique(row[i],row[i]+m)-row[i];
    }
    for(int j=0;j<m;++j)
    {
        sort(col[j],col[j]+n);
        col_end[j]=unique(col[j],col[j]+n)-col[j];
    }
    for(int i=0;i<n;++i)
    {
        for(int j=0;j<m;++j)
        {
            int x=lower_bound(row[i],row[i]+row_end[i],plat[i][j])-row[i];
            int y=lower_bound(col[j],col[j]+col_end[j],plat[i][j])-col[j];
            cout<<max(x,y)+max(row_end[i]-x,col_end[j]-y)<<" ";
        }
        cout<<endl;
    }
    return 0;
}

  D:

    给定两个01串,s和t,求对s进行重排使得t在s中出现的次数最多

    可用kmp或者hash来做(hash还没填坑emmm).学习了kmp,

    题解:

    可知构造的新的s'满足如下条件:把由t求出来的next数组进行无线延长,使len(t)以后的next数组是一直严格递增的,直到0的数量或者1的数量为0为止,输出剩下的0或1

    代码如下:

    

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=5e5+5;
 4 char s[maxn],t[maxn];
 5 int nex[maxn];
 6 int s1,s0,t1,t0;
 7 void getnext(char *p)
 8 {
 9     int i=0,j=-1;
10     nex[0]=-1;
11     int len=strlen(p);
12     printf("%s",p);
13     while(i<len)//构造next数组
14     {
15         if(j==-1 || p[i]==p[j])
16         {
17             nex[++i]=++j;
18         }
19         else j=nex[j];
20     }
21     s1-=t1,s0-=t0;
22     while(s1 && s0)//当s中1和0有剩余的时候,保持next数组增长
23     {
24         p[i]='0';
25         if(p[i]==p[j]&&p[i]=='0')
26         {
27             putchar('0');
28             nex[++i]=++j;
29             --s0;
30         }
31         else
32         {
33             putchar('1');
34             p[i]='1';
35             nex[++i]=++j;
36             --s1;
37         }
38     }
39     //输出剩余的0和1
40     for(int q=1;q<=s1;++q) putchar('1');
41     for(int q=1;q<=s0;++q) putchar('0');
42 }
43 int main()
44 {
45     scanf("%s%s",s,t);
46     int lens=strlen(s),lent=strlen(t);
47     for(int i=0;i<lens;++i) {
48         if(s[i]=='0') ++s0;
49         else ++s1;
50     }
51     for(int i=0;i<lent;++i) {
52         if(t[i]=='0') ++t0;
53         else ++t1;
54     }
55     if(s1<t1 || s0<t0){puts(s); return 0;}
56     getnext(t);
57 }

 

posted @ 2019-04-09 18:52  codeoos  阅读(194)  评论(0编辑  收藏  举报