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 }