[题传送门](Problem- 525C - Codeforces)
气死了,为什么调不了啊啊啊啊啊啊啊啊凸(艹皿艹 )。 好吧,今天其实是两个的题,一个是场一个是场。
题1思路
一眼发现是二分,关键在于我第一次写的二分时间复杂度还是超了,思路很简单,二分,但是如果二分之后暴力枚举每个字母的是否满足这个,那么就算经过小的剪枝优化,那么时间复杂度依然高达,这个复杂度就比较性感,我当时算的是可以过的,但是忘了考虑的时间复杂度,于是乎时间复杂度计算错误,成功在 了,后来找题解发现确实是二分,但是可以用一个大小为的数组在一路遍历的时候记录,因为我们知道对于每个字母,那么可以管辖的区间就是,但是由于我们是从前往后跑,所以只要考虑前一个区间,我们只需要对每个的,如果这个区间某个字母出现次数为,那么这个区间一定不满足,然后把之前出现的字母次数。最后我们看看有没有字母能不能满足跑下来,如果有那么我们就 。否则我们就 。
代码
#include <bits/stdc++.h>
#define ll long long
#define x first
#define y second
using namespace std;
string s;
int len;
bool flag[26];
int res[26];
bool check(int m){
memset(flag,0,sizeof flag);
memset(res,0,sizeof res);
for(int i=0;i<len;i++){
res[s[i]-'a']++;
if(i>=m-1){
for(int j=0;j<26;j++){
if(res[j]==0) flag[j]=true;
}
res[s[i-m+1]-'a']--;
}
}
for(int i=0;i<26;i++){
if(!flag[i]) return true;
}
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin>>s;
len=s.size();
int l=1,r=len;
int ans=0;
while(l<r){
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l;
return 0;
}
题2思路
这题是个贪心,我们降序排序所有的边,然后我们看相邻的边是否满足满足就把较短的边变成长,然后找宽,找到之后把长和宽再变成,最后输出答案即可。是个模拟贪心。
代码
#include <bits/stdc++.h>
#define ll long long
#define x first
#define y second
using namespace std;
ll ans=0;
int n;
ll w[100010];
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++) cin>>w[i];
sort(w+1,w+n+1);
reverse(w+1,w+n+1);
ll l=w[1],r=-1;
int cntl=1,cntr=0;
for(int i=2;i<=n;i++){
if(cntl<2){
if(cntl==0){
l=w[i];
cntl++;
}
else if(w[i]==l || w[i]+1==l){
cntl++;
l=w[i];
}
else{
l=w[i];
}
}
else if(cntr<2){
if(cntr==0){
r=w[i];
cntr++;
}
else if(w[i]==r || w[i]+1==r){
cntr++;
r=w[i];
}
else r=w[i];
}
if(cntl==2 && cntr==2){
cntl=0,cntr=0;
ans+=l*r;
}
}
cout<<ans;
return 0;
}