Codeforces Round #767 (Div. 2) 小结
Problem A
Download More RAM
思路
签到题,将软件按\(a_i\)值从小到大排序,模拟即可。
Problem B
GCD Arrays
思路
同样是签到题,由于给定的是一段连续自然数,我们令最终的gcd=2即可,这样操作次数是最少的。简单来说,我们将一个奇数和一个偶数合并,最小操作次数就是这段区间内奇数的个数。
若奇数个数 \(\geq k\) 则无解。
注意特判 \(l=r\) 的情况
Problem C
Meximum Array
思路
用了一种比较奇特的做法
yy一下可知,贪心算法是可行的,每一次取当前最大的mex值,当存在mex相同时,取最靠前的。
怎样维护mex以及找到mex最大的位置?
既然这是一道Div2的C题,那么高级数据结构就不用考虑了,不会那么难。(我还傻乎乎地考虑了怎么动态维护区间Mex。。。)
注意到题目条件\(0 \leq a_i \leq n\),这启示我们从值域上去考虑。
维护每一个值\(a_i\)第一次出现的位置\(p[a[i]]\),依次验证是否存在 \(j\) 使 \(mex[j]=0,1,2...\)
如果存在\(mex[j]=x\),那么必然有\(j\geq max(p[0],p[i],...,p[x-1])\)且等号能取到。
于是我们就确定了应该取数的值和位置(当首次发现\(x\)不存在对应的\(j\)时,因为mex不能取到x+1了)。
我在说些什么。。。[笑哭](结合代码理解吧)
代码
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define maxn 200010
using namespace std;
int a[maxn];
int nxt[maxn],pre[maxn],fst[maxn],last[maxn];
int b[maxn],cnt=0;
void init(int n){
cnt=0;
for(int i=0;i<=n;++i){
nxt[i]=fst[i]=pre[i]=last[i]=0;
}
}
int main(){
int i,j;
int t;
int n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=n;++i) scanf("%d",&a[i]);
init(n);
for(i=1;i<=n;++i){
if(!last[a[i]]) fst[a[i]]=i;
pre[i]=last[a[i]];
last[a[i]]=i;
nxt[pre[i]]=i;
}
int p=0,q=1;
while(q<=n){
if(q==n){
if(a[q]==0) b[++cnt]=1;
else b[++cnt]=0;
break;
}
for(i=0;i<=n;++i){
if(!fst[i]) break;
p=max(p,fst[i]);
}
b[++cnt]=i;
if(i==0){
p=q;
fst[a[p]]=nxt[p];
}
else{
for(i=q;i<=p;++i){
if(nxt[i]<=p&&nxt[i]>0) continue;
fst[a[i]]=nxt[i];
}
}
q=p+1;
}
printf("%d\n",cnt);
for(i=1;i<=cnt;++i){
printf("%d ",b[i]);
}
printf("\n");
}
// system("pause");
return 0;
}
Problem D
Peculiar Movie Preferences
比赛时想到了正解,但是时间不够没调出来。
思路
首先如果给定的字串\(s\)中本来就有回文串(包括长度为1的串),那必然YES。
于是我们可以认为只有长度为2和3的串。
手玩下样例,猜个结论:若存在回文串,必然存在两个原串拼起来的回文串(证明见tutorial)。
然后就做完了。
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define maxn 100010
using namespace std;
char s[maxn][4];
int book[27][27][27],ans=0;
void init(){
int i,j,k;
ans=0;
for(i=0;i<=26;++i)
for(j=0;j<=26;++j)
for(k=0;k<=26;++k)
book[i][j][k]=0;
}
int main(){
int i,j,n,m;
int T;
scanf("%d",&T);
while(T--){
int flag=0;
scanf("%d",&n);
init();
for(i=1;i<=n;++i) scanf("%s",s[i]);
for(i=1;i<=n;++i){
int L=strlen(s[i]);
if(L==1||L==3&&s[i][0]==s[i][2]||L==2&&s[i][0]==s[i][1]){
flag=1;
break;
}
}
if(flag) ans=1;
else{
for(i=1;i<=n;++i){
int x,y,z;
if(strlen(s[i])==2){
x=s[i][0]-'a'+1;
y=s[i][1]-'a'+1;
z=0;
for(j=0;j<=26;++j){
if(book[y][x][j]){
ans=1;
break;
}
}
book[x][y][0]=1;
if(ans) break;
}
else{
x=s[i][0]-'a'+1;
y=s[i][1]-'a'+1;
z=s[i][2]-'a'+1;
if(book[z][y][x]||book[z][y][0]){
ans=1;
break;
}
book[x][y][z]=1;
if(ans) break;
}
}
}
if(ans) printf("YES\n");
else printf("NO\n");
}
// system("pause");
return 0;
}
还是得提升中档题的思考速度啊QWQ