C - Challenging Cliffs
重新排序数组使得|a1-an|最小
还要在最大化h[i]≤h[i+1]的数量的前提下
int n,h[maxn],pos,mi;
void solve()
{
sd(n);
rep(i,1,n)sd(h[i]);
sort(h+1,h+1+n);
pos=1,mi=h[2]-h[1];
rep(i,3,n)
{
if(h[i]-h[i-1]<mi)
{
mi=h[i]-h[i-1];
pos=i-1;
}
}
pdk(h[pos]);
rep(i,pos+2,n)pdk(h[i]);
rep(i,1,pos-1)pdk(h[i]);
pd(h[pos+1]);
}
D - Deleting Divisors
玩游戏
每个回合能将n减去一个它的因子(1,n除外)
谁不能操作谁输
----盲猜跟质因子个数相关
打表发现:
奇数与2的奇数次幂都不行
int n;
void solve()
{
sd(n);
if(n&1)
{
puts("Bob");return;
}
int cnt=0;
while(n%2==0)n/=2,cnt++;
if(n==1&&(cnt&1))
{
puts("Bob");
return;
}
puts("Alice");
}
E12Erase and Extend (Hard Version)
给你一个字符串
两种操作:
1、删去最后一个字符
2、s:=s+s
可以操作任意次
要获得长度为k的字典序最小的字符串
----盲猜肯定先删再翻倍然后再将字符串长度删到k
记录每个字符出现的位置 (其实只要第一个字符)
如果后面存在字符比第一个字符大,就把那个字符位置截断,使得字符串只包含比第一个字符小或等于的字符
之后比较枚举第一个字符出现的位置,将那段字符串与第一段字符串比较
int n,k,las;
char s[maxn],ans[maxn];
vector<int>vec[30];
void solve()
{
sdd(n,k);
sc(s);
rep(i,0,n-1)vec[s[i]-'a'].pb(i);
las=n-1;
int fir=s[0]-'a';
rep(i,fir+1,25)if(vec[i].size())las=min(las,vec[i][0]-1);
while(vec[fir].back()>las)vec[fir].pop_back();
vec[fir].pb(las+1);
int si=vec[fir].size(),nd=0;
int L=1;
while(L<=las&&s[L]==s[0])L++;
if(L>las)
{
rep(i,1,k)printf("%c",s[0]);
puts("");
return;
}
rep(i,1,si-2)
{
int now=i+1;
while(now<=si-2&&vec[fir][now]==vec[fir][now-1]+1)now++;
if(now-i<L)
{
i=now-1;
nd=i;
continue;
}
if(now-i>L)break;
int len1=vec[fir][L];
int len2=vec[fir][now]-vec[fir][i];
int ju=0;
rep(j,1,min(len1,len2)-1)
{
if(s[j]>s[vec[fir][i]+j])
{
ju=1;break;
}
if(s[j]<s[vec[fir][i]+j])
{
ju=-1;break;
}
}
if(!ju&&len1>len2||ju==-1)break;
i=now-1;
nd=i;
}
int Len=vec[fir][nd+1];
while(Len>1&&s[Len-1]==s[0])Len--;
rep(i,0,k-1)ans[i]=s[i%Len];
printf("%s\n",ans);
}