B. Chemistry
题意: 删除k个元素后能否组成一个回文序列(可任意排列)
思路:计算有多少个奇数的字母,如果最后(n-k)剩偶数个,就看k次能不能把奇数减去;如果最后剩奇数个,看k次能不能把奇数减一个 减去,
收获:思路要想的深一步,不要想到就写,有可能写复杂了。多想一下,可以有更简洁的方法
void solve()
{
int cntji=0,cntou=0;
memset(a,0,sizeof a);
cin>>n>>k>>s;
for(int i = 0;i<n;i++) a[s[i]-'a']++;
for(int i = 0;i<=25;i++)
{
if(a[i]==0)continue;
if(a[i]%2==1)cntji++;
else cntou++;
}
if((n-k)%2==0)
{
if(k>=cntji)cout<<"Yes\n";
else cout<<"No\n";
}
else
{
if(k>=cntji-1)cout<<"Yes\n";
else cout<<"No\n";
}
}
C. Raspberries
题意:对ai进行多少次加一操作,使得a1*a2*a3*an可被k整除
思路:对所有k暴力求解一次,再特判k=4的时候
收获,可以注意到2<=k<=5,范围非常小,且 2,3,5都是质数,很好判断,再单独判断4这个特殊情况。代码写时,注意先把所有的k都求出来,再单独求k=4,比较好求
int n,k;
const int N=2e5+10;
int a[N];
void solve()
{
cin>>n>>k;
for(int i = 1;i<=n;i++)cin>>a[i];
int ans=1e8;
for(int i = 1;i<=n;i++)
{
int t;
t=(a[i]/k+1)*k-a[i];
if(a[i]%k==0)t=0;
ans=min(ans,t);
}
if(k==4)
{
int t;
int ou=0;
int ji=0;
for(int i = 1;i<=n;i++)
{
if(a[i]%2==0)ou++;
else ji++;
}
if(ou>=2)t=0;
else if(ou==1)t=1;
else t=2;
ans=min(ans,t);
}
cout<<ans<<endl;
}
D. In Love
题意:将区间加入或删除,判断是否存在不相交的区间
思路:使用multiset(可重复且自动排序),存起来左和右的值,判断左最大和右最小的大小
收获:学习multiset的用法,
multiset<int> l,r;
void solve()
{
char s;
int a,b;
cin>>s>>a>>b;
if(s=='+')
{
l.insert(a);
r.insert(b);
}
else
{
l.erase(l.find(a));
r.erase(r.find(b));
}
if(l.size()>1 && *l.rbegin()>*r.begin())yes;
else no;
}
E. Look Back
题意:操作为ai乘2,求多少次操作使a变为一个不减序列
思路:将每次变化数记录下来,如果后比前大的话,就是负数。ans每次加前缀和,如果前缀和为负,就变成0
收获:传统思路会爆long long 和 int,利用前缀和优化
#define int long long
int n;
const int N=2e5+10;
int a[N],b[N];
void solve()
{
cin>>n;
for(int i = 1;i<=n;i++) cin>>a[i];
for(int i = 2;i<=n;i++)
{
int s=0;
if(a[i]>=a[i-1])
{
while((a[i]>>s)>=a[i-1])s++;
b[i]=1-s;
}
else
{
while((a[i]<<s)<a[i-1])s++;
b[i]=s;
}
}
int ans=0,sum=0;
for(int i = 2;i<=n;i++)
{
sum+=b[i];
if(sum<0)sum=0;
ans+=sum;
}
cout<<ans<<endl;
}