A题: A. Split it!
题意就是问一个字符串长度为n 你能不能把它分割k次
然后使得根据题意公式重新组成S串
解题:统计回文长度+判断即可
char s[5000];
signed main(){
ll t;
read(t);
while(t--){
ll n,k;
read(n);
read(k);
scanf("%s",s+1);
ll res = 0;
for(int i = 1,j = n;j - i >= 1;i++,j--){
if(j - i <= 1) break;
if(s[i] == s[j]) res++;
else break;
}
if(res >= k) puts("YES");
else puts("NO");
}
}
B. Max and Mex
一个多重集合,现在你可以操作K次:每次把最大值和集合的mex运算后重新加入集合,求k次以后集合有多少个不同的数
其实这是有特点的
我们需要对小于n的数标记一下,每个数也要另外标记。
然后巴拉巴拉
const int maxn=1e5+77;
ll vis[maxn];
ll pre[maxn];
ll check(ll x){
if(!vis[x]) return x;
return pre[x] =check(pre[x]);
}
map<ll,ll>s;
signed main(){
ll t;
read(t);
while(t--){
ll n,m;
read(n);
read(m);
ll ma=0,mex =0;
ll ans=n;
for(int i=0;i<=n+1;i++) vis[i] = 0,pre[i] = i+1;
ll vel=0;
for(int i=1;i<=n;i++){
ll x;
read(x);
if(x<=n){vis[x]=1,vel++;}
s[x] = 1;
ma=max(ma,x);
}
ll op=0;
for(int i=1;i<=m;i++){
mex =check(op);
if(mex>n){
ans=ans+m-i+1;
break;
// max=n
}
ll pos=(mex+ma+1)/2;
if(s[pos]!=0) break;
else{
if(pos<=n)vis[pos]=1;
s[pos]=1;
ans++;
}
}
s.clear();
printf("%lld\n",ans);
}
return 0;
}
C题更水了 大的相匹配 开方会更优。
重点说下D吧 其实就是一个前缀后缀处理加一点点思维
假设当前我们选的x x左右可以走的距离为L【x】 R【x】
我们先判断一下L前缀的最大值出现了多少次。如果不少于1次,那么一定不论如何都是必败,答案为0,因为对方可以走一样的步数,先手必败。判断R后缀同理。最后我们要处理一下L【pos】跟R【pos】是否有解 注意当两者相等是只能是奇数才能获胜。
const int N=100005;
int n,a[N],L[N],R[N],ans,cnt,flag,Max;
signed main()
{
read(n);
for (int i=1; i<=n; i++)
read(a[i]);
L[1]=1;
for (int i=2; i<=n; i++)
if (a[i]>a[i-1])
L[i]=L[i-1]+1;
else
L[i]=1;
R[n]=1;
for (int i=n-1; i; i--)
if (a[i]>a[i+1])
R[i]=R[i+1]+1;
else
R[i]=1;
for (int i=1; i<=n; i++)
Max=max(Max,max(L[i],R[i]));
for (int i=1; i<=n; i++)
if (L[i]==Max)
{
if (flag)
{
puts("0");
return 0;
}
flag=i;
}
for (int i=1; i<=n; i++)
if (R[i]==Max)
{
if (flag!=i&&flag)
{
puts("0");
return 0;
}
flag=i;
}
int i=flag;
if (L[i]==R[i]&&L[i]%2==1)
puts("1");
else
puts("0");
}