Codeforces Round #733 (Div. 1 + Div. 2)题解
快两年没有碰OI了orz,打一次直接橙变紫掉200分。
A题 水题
B题 水题
C题 水题
D题
贪心,可以想到有多少个不同的a[i]就有多少最终答案。匹配上,贪心选择,然后乱匹配。如果发现i自己对应自己了,那么将i对应向a[i],而a[i]对应的人对上自己就可以了。
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
int n,T;
int a[200005],b[200005];
int cnt[200005];
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d",&n); int m = 0;
for(int i=1;i<=n+1;i++) cnt[i] = 0,a[i]=b[i]=0;
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
if(!cnt[a[i]]) {
m++; b[i] = a[i]; cnt[a[i]] = i;
}
}
int zz = 1;
for(int i=1;i<=n;i++) {
if(!b[i]) {
while(cnt[zz]) zz++;
b[i] = zz; cnt[zz] = i; zz++;
}
}
// cerr<<cnt[3]<<"fu"<<endl;
printf("%d\n",m);
for(int i=1;i<=n;i++) {
if(b[i]==i) {
b[i] = a[i];
b[cnt[a[i]]] = i;
cnt[a[i]] = i;
}
}
for(int i=1;i<=n;i++) printf("%d ",b[i]);
puts("");
}
}
E题 感觉好难的构造题
情况1:所有字母相同 直接输出
情况2:存在某个字母只出现过一次 放在开头,f = 0
情况3:所有字母均出现2次+
可以将一个a(最小字典序字母)放开头+b+末尾全放a保证f=1但由于需要字典序 SO....
情况3.1:将aa放开头,保证字典序最小且不超f=1,然后可以想到之后的a不能再跟a,要么放末端,要么后加非a字母,假设全长为L,a的个数为cnt,可以想到需要cnt-1 <= L-cnt+1才可以这么构造,其余位置字典序构。
情况3.2: 迫不得已只能开头一个a,那么在a后加一个b(第二字典序字母),之后全加a,a后跟一个c(第三字典序字母)然后字典序构即可。
情况3.2:如果没有c?那只能a后面全放b再加a了。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<queue>
#include<cstdio>
#include<cmath>
using namespace std;
char s[100005];int st[100005];
int nm[30],A,B,C;
void pt(int x) {
putchar(x+'a'-1);
nm[x]--;
}
void solve() {
for(int i=1;i<=26;i++) nm[i] = 0;
A = B = C = 0;
//init
scanf("%s",s+1);
int le = strlen(s+1);
for(int i=1;i<=le;i++) {
nm[s[i]-'a'+1]++;
}
int dzm = 0;
for(int i=1;i<=26;i++) {
if(nm[i]) {
if(!A) A = i;
else if(!B) B = i;
else if(!C) C = i;
}
}
for(int i=26;i>=1;i--) if(nm[i]==1) dzm=i;
if(!B) {
while(le--) pt(A);
puts("");
// cerr<<"op1";
return;
} // op1
else if(dzm) {
pt(dzm);
for(int i=1;i<=26;i++) {
while(nm[i]) pt(i);
}
puts("");
// cerr<<"op2";
return;
}// op2
else if(nm[A]-1<=le-nm[A]+1) {
pt(A);pt(A);
int stle = 0;
for(int i=1;i<=26;i++) {
if(i!=A) {
int oo = nm[i];
while(oo--) {
st[++stle] = i;
}
}
}
stle = 0;
for(int i=3;i<=le;i++) {
if((i&1)==0&&nm[A]) pt(A);
else pt(st[++stle]);
}
// cerr<<"op3";
puts(""); return;
} else if(C) {
pt(A); pt(B);
while(nm[A]) pt(A);
pt(C);
for(int i=1;i<=26;i++) {
while(nm[i]) pt(i);
}
puts(""); return;
} else {
pt(A);
while(nm[B]) pt(B);
while(nm[A]) pt(A);
puts(""); return;
}
}
int main(){
int T; scanf("%d",&T);
while(T--) solve();
return 0;
}
未完待续。。

浙公网安备 33010602011771号