[CodeForces1138]
B Circus
-
题意
给你n个演员的信息(能否演马戏,能否演小丑)
把他们分成两批,使得第一批中能演马戏的演员数量等于第二批中能演小丑的人的数量
吐槽:div2B什么时候这么毒瘤了
-
solution
枚举:第一批中又能演马戏又能演小丑的人数和第一批中两个都不能演的人数
然后第二批相应项的人数也可以算出来
也就是说,剩下的问题就是剩下两种人的分配,
然后我们发现,这两种人的分配方式对答案(第一批中演马戏的人数减第二批中演小丑的人数)没有影响
然后你就A了这题
-
code
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 5050
using namespace std;
struct zero{
int a,c;
}lib[N];
int n;
string s;
int ans[N];
int cnt[4];
bool op=true;
int main(){
scanf("%d",&n);
cin>>s;
for(int i=0;i<n;i++)lib[i+1].a=s[i]-'0';
cin>>s;
for(int i=0;i<n;i++)lib[i+1].c=s[i]-'0';
for(int i=1;i<=n;i++){
if(lib[i].a+lib[i].c==0)cnt[0]++;//0 0
else if(lib[i].a==1&&lib[i].c==0)cnt[1]++;//1 0
else if(lib[i].a+lib[i].c==1)cnt[2]++;//0 1
else cnt[3]++;//1 1
}
for(int i=0;i<=cnt[0];i++)//0 0
for(int r=0;r<=cnt[3];r++){
if((cnt[0]-i)+(cnt[3]-r)>n/2||i+r>n/2)continue;
int now1=r,now2=cnt[3]-r;
int needs=n/2-i-r;
int to1=now1,to2=now2;
int ans1,ans2;
if(needs<=cnt[1]){
to1+=needs;
to2+=cnt[2];
ans1=needs,ans2=0;
}
else {
to1+=cnt[1];
to2+=n/2-(cnt[0]-i)-(cnt[3]-r);
ans1=cnt[1];
ans2=needs-cnt[1];
}
if(to1==to2){
ans[0]=i,ans[1]=ans1,ans[2]=ans2,ans[3]=r;
for(int i=1;i<=n;i++){
if(lib[i].a==0&&lib[i].c==0&&ans[0]>0){printf("%d ",i);ans[0]--;}
if(lib[i].a==1&&lib[i].c==0&&ans[1]>0){printf("%d ",i);ans[1]--;}
if(lib[i].a==0&&lib[i].c==1&&ans[2]>0){printf("%d ",i);ans[2]--;}
if(lib[i].a==1&&lib[i].c==1&&ans[3]>0){printf("%d ",i);ans[3]--;}
}
return 0;
}
}
puts("-1");
}
C Skyscrapers
-
题意
给你一个n\(\times\)m的矩阵input,第 i 行第r列表示input[i][r]的高度
对于每一个点你需要把该点所在的行和列一起离散化,输出需要用到的最大数字
吐槽:这题坑死我了,到2:29:47才A(并且达成成就:绝杀)
-
solution
我们把每一行,每一列拆出来单独离散化,记录每个点在离散数组中的排名
即对于一个点(i,r) 把(离散数组中)这个点前面有几个点记下来,后面有几个点记下来
然后在查询时整合一下该点的信息即可
-
code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 2005
using namespace std;
int pl1[N][N];
int pl2[N][N];
int l1[N][N],r1[N][N];
int l2[N][N],r2[N][N];
int plk[N];
int n,m;
int input[N][N];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int r=1;r<=m;r++)scanf("%d",&input[i][r]);
for(int i=1;i<=n;i++){
for(int r=1;r<=m;r++)plk[r]=input[i][r];
sort(plk+1,plk+m+1);
int tot=unique(plk+1,plk+m+1)-plk-1;
for(int r=1;r<=m;r++){
pl1[i][r]=lower_bound(plk+1,plk+tot+1,input[i][r])-plk;
l1[i][r]=pl1[i][r]-1;
r1[i][r]=tot-pl1[i][r];
}
}
for(int i=1;i<=m;i++){
for(int r=1;r<=n;r++)plk[r]=input[r][i];
sort(plk+1,plk+n+1);
int tot=unique(plk+1,plk+n+1)-plk-1;
for(int r=1;r<=n;r++)
{pl2[i][r]=lower_bound(plk+1,plk+tot+1,input[r][i])-plk;
l2[i][r]=pl2[i][r]-1;
r2[i][r]=tot-pl2[i][r];}
}
for(int i=1;i<=n;i++){
for(int r=1;r<=m;r++){
printf("%d ",(max(r1[i][r],r2[r][i])+max(l1[i][r],l2[r][i]))+1);
}
putchar('\n');
}
}
D.Camp Schedule
-
题意
给你字符串s1,s2,你可以重新排列s1,使得s2在s1中出现次数尽可能多(出现位置可以重叠)
-
solution
kmp裸题
求出s2的kmp数组,每次构造完一个s2后从\(kmp[s2.size()]+1\)处开始构造而不是从头构造
吐槽:D题怎么这么水
-
code
#include<bits/stdc++.h>
using namespace std;
int kmp[1000005];
int pos=0;
char s1[1000005],s2[1000005];
int cnt1=0,cnt2=0;
int main(){
cin>>s1+1;
cin>>s2+1;
int n=strlen(s1+1),m=strlen(s2+1);
for(int i=2;i<=m;i++){
while(pos&&s2[pos+1]!=s2[i])pos=kmp[pos];
if(s2[pos+1]==s2[i])pos++;
kmp[i]=pos;
}
for(int i=1;i<=n;i++){
if(s1[i]=='0')cnt1++;
else cnt2++;
}
for(int i=1;i<=m;i++){
if(s2[i]=='0')cnt1--;
else cnt2--;
}
if(cnt1<0||cnt2<0){cout<<(s1+1);return 0;}
cout<<(s2+1);
int poss=m;
bool op=true;
for(;cnt1&&cnt2&&op;){
poss=kmp[m]+1;
for(int i=poss;i<=m&&op;i++){
if(s2[i]=='0'){if(!cnt1){op=false;break;}
putchar('0'),cnt1--;
}
else {if(!cnt2){op=false;break;}putchar('1'),cnt2--;}
}
}
for(int i=1;i<=cnt1;i++)putchar('0');
for(int i=1;i<=cnt2;i++)putchar('1');
}
E.Museums Tour
咕咕咕……
F.Cooperative Game
-
题意
先咕着
-
solution
floyd判环/龟兔赛跑判环裸题,不解释
-
code
#include<bits/stdc++.h>
using namespace std;
int n;
string s;
int aux(){
scanf("%d",&n);
getline(cin,s);
return n;
}
int main(){
do{
puts("next 0 1");
fflush(stdout);
aux();
puts("next 0");
fflush(stdout);
}while(aux()!=2);
do{
puts("next 0 1 2 3 4 5 6 7 8 9");
fflush(stdout);
}while(aux()!=1);
puts("done");
fflush(stdout);
}