为了能到远方,脚下的每一步都不能少.|

园龄:粉丝:关注:

2025牛客寒假算法基础集训营2

A

没有4和7就可以

B

给一个数组,长度为n,找一个数比数组中一半的数都小的最大的数

无论n为奇数还是偶数ans=a[n/2+1]1(整除的特性)

D

牛可乐定义字符串 𝑠的可爱度 𝑘为这样的一个最大整数,使得存在长度为 𝑘的连续子串,a、长度为 k 的不连续子序列
b满足 ,a=b特别地,若不存在符合要求的 a,b,则可爱度为 0
现在,对于给定的字符串 s,求解其可爱度。

子串
为从原字符串中,连续的选择一段字符(可以全选、可以不选)得到的新字符串。
仅在本题中,不连续子序列,定义为至少由两段不相邻的非空子串构成。

solution:

贪心地来想,只要a串最后一个字符,在之后的字符出现过,那么就可以构造这样一个b串使得a=b

  • attention: 那么这样反过来,那需考虑
#include<bits/stdc++.h>
using namespace std;
map<char,int> mp;
int n;
string s;

int main(){
    cin>>n;
    cin>>s;
    int lens=s.length();
    for(int i=0;i<lens;++i) mp[s[i]]++;
    int ans=0;
    for(int i=0;i<lens;++i){
        mp[s[i]]--;
        if(mp[s[i]]>0) ans=max(ans,i+1);
    }
    for(int i=0;i<lens;++i) mp[s[i]]++;
    reverse(s.begin(),s.end());
    for(int i=0;i<lens;++i){
        mp[s[i]]--;
        if(mp[s[i]]>0) ans=max(ans,i+1);
    }
    cout<<ans<<endl;
    return 0;
}

C

C和D是相反的,C考虑如何构造一个长度为n字符串s使得可爱度等于m

和D反过来想,我们直接地任意构造前m个字符串,但是最后n-m个字符一定满足sm=si(i[nm+1,n])同时sisj(i,j[nm+1,n])

据此nm<=26 因为最多有26个字母不同

但是如果我们只正向考虑,那么反过来找可爱度就会很大,所以也要考虑前n-m个数也要满足刚刚的条件,这时也需要满足上述条件,至于中间的2*m-n个数与sm相同即可

这时考虑一点:当2mn<=0时,2(nm)>n,所以要及时停止输出

还有一点,容易得到n==m肯定无解

#include<bits/stdc++.h>

using namespace std;

int t;
int n,m;

void solve(){
    cin>>n>>m;
    if(n==m||m<n-26){
        puts("NO");
        return ;
    }
    puts("YES");
    string ans;
    int cnt=0;//记录构造的字符串多长
    for(int i=1;i<=n-m;++i,++cnt)
        cout<<char('a'+(i-1)%(n-m));
    for(int i=1;i<=2*m-n;++i,++cnt) 
        cout<<char('a'+n-m-1);
    for(int i=1;i<=n-m && cnt<=n;++i,++cnt)
        if(cnt==n) break;//超过长度就结束
        else cout<<char('a'+(i-1)%(n-m));
    cout<<endl;
    return ;
}

int main(){
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

还有一种构造方式

for (int i = 0; i < n; i++) {
      cout << (char)('a' + i % (n - m));
}

F

通过这个位运算表达式,可以知道只有,同一位都是0,才取0,否则都为1

所以只有x=y时,表达式成立
(注意数据范围)

#include<bits/stdc++.h>

using namespace std;

int t;
long long l,r;


int main(){
    cin>>t;
    while(t--){
        cin>>l>>r;
        cout<<(long long )r-l+1<<endl;
    }return 0;
}

G

设添柴火的次数为x,由题
(次数一定大于等于1)

mx<n<mx+1

取对数
xlnm<lnn<(x+1)lnm

得到
logmn1<x<logmn

x=(logmn)

#include<bits/stdc++.h>

using namespace std;
int n,m;
int t;
int quick_pow(int a,int b){
    if(b==0) return 0;
    int base=a;
    int ans=1;
    while(b){
        if(b&1) ans*=base;
        base*=base;
        b>>=1;
    }return ans;
    
}
void solve(){
    int ans=1;
    cin>>n>>m;
    if(m==1 || m>2*n){
        puts("1");
        return ;
    }
    long double l=log(n)/log(m)-1;
    long double r=log(n)/log(m);
    int dis=1e9;
    int x=r;
    for(int i=x-2>0?x-2:0;i<=x+2;++i){
        if(abs(n-quick_pow(m,i))<dis){
           ans=i;
           dis=abs(n-quick_pow(m,i)); 
        }
    }
    cout<<ans<<endl;
    return ;
}
int main(){
    cin.tie(0);
    cout.tie(0);
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

J

纯模拟,注意细节,时间段是闭区间

代码给出了不好的示范

其实可以考虑用scanf输入,可以很好的把时间扣出来

#include<bits/stdc++.h>

using namespace std;
int n;
string h,m;


const int maxn=1e5+10;
map<string,bool> mp[4];
int ans[5];
void solve(){
    cin>>n>>h>>m;
    memset(ans,0,sizeof(ans));
    mp[1].clear();
    mp[2].clear();
    mp[3].clear();
    if(m.size()==1) m='0'+m; 
    for(int i=1;i<=n;++i){
        string id,date,time;
        cin>>id>>date>>time;
        string year,month;
        for(int j=0;j<=6;++j){
            if(j<4) year+=date[j];
            if(j>4) month+=date[j];
        }
        if(year!=h || month!=m) continue;
        int hh=(time[0]-'0')*10+time[1]-'0';
        int h3=(time[3]-'0')*10+time[4]-'0';
        int h4=(time[6]-'0')*10+time[7]-'0';
        if((hh>=7 && hh<9)||(hh>=18 && hh<20)||(hh==9 &&h3==0 && h4==0)||((hh==20 &&h3==0 && h4==0))){
            if(mp[1][id]) continue;
            mp[1][id]=1;
            ans[1]++;
        }
        else if((hh>=11&&hh<13)||((hh==13 &&h3==0 && h4==0))){
            if(mp[2][id]) continue;
            mp[2][id]=1;
            ans[2]++;
        }
        else if(hh>=22 || hh<1 || (hh==1 &&h3==0 && h4==0)){
            if(mp[3][id]) continue;
            mp[3][id]=1;
            ans[3]++;
        }
    }
    for(int i=1;i<=3;++i) cout<<ans[i]<<" ";
    return ;
}
int main(){
    cin.tie(0);
    cout.tie(0);
    
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

K

基础的dfs,对于一个连通块,找边界有多少块相邻的瓷砖

#include<bits/stdc++.h>

using namespace std;
int n,m;
const int maxn=510;
bool mp[maxn][maxn];
bool book[maxn][maxn];
int ans=maxn*maxn;
int cnt=0;
int nt[5][3]={{1,0},{0,1},{0,-1},{-1,0}};
void dfs(int i,int j){
    if(i<1 || i>n || j<1 || j>m ) return ;
    if(mp[i][j]==0){
        ++cnt;
        return ;
    }
    for(int x=0;x<4;++x){
        int ni=i+nt[x][0];
        int nj=j+nt[x][1];
        if(book[ni][nj]) continue;
        book[ni][nj]=1;
        dfs(ni,nj);
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;++i){ 
        string s;cin>>s;
        for(int j=1;j<=m;++j)
            mp[i][j]=s[j-1]-'0';
    }
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j){
            if(book[i][j]==0 && mp[i][j]==1){
                cnt=0;
                dfs(i,j);
                ans=min(ans,cnt);
            }
        }
    cout<<ans<<endl;
    return 0;
}

E

一个数组a,给定区间[l,r],可以对ai,foralli[l,r],+1or1,使得foralli[l+1,r],t=l+1t=iatai
而且+1,-1会在操作后清空

很容易地贪心地想,如果我们给最左端+x,那么一定到某个数时,一定可以使条件满足

我们设前缀和f,即需要满足i[l+1,r],f[i1]f[l1]+x=a[i] tox=max(a[i]f[i1])+f[l1]

由于是+1后会清空,所以可以用静态查找最大值,用ST表


#include<bits/stdc++.h>

using namespace  std;
#define ll long long
int n,q;
const int maxn=2e5+10;
int lg[maxn];
ll st[maxn][40];
ll f[maxn];
ll d[maxn];
void fun_st(){
	for(int j=1;j<=lg[n];++j)//区间长度 
		for(int i=1;i<=n-(1<<j)+1;++i){
			st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
		}
	
}
int main(){cin.tie(0);cout.tie(0);
	cin>>n>>q;
	lg[1]=0;
	for(int i=2;i<=maxn;++i) lg[i]=lg[i>>1]+1;
	for(int i=1;i<=n;++i){
		int x;cin>>x;
		f[i]=f[i-1]+x;
		d[i]=x-f[i-1];
		st[i][0]=d[i];
	}
	fun_st();
	while(q--){
		int l,r; 
		cin>>l>>r;
		if(l==r) {
			cout<<0<<"\n";
			continue;
		}
        
		int t=lg[r-(l+1)+1];
		ll cnt=max(st[l][t],st[r-(1<<t)+1][t]);
		ll ans=max(cnt+f[l-1],0ll);
		cout<<ans<<endl; 
	}
}

本文作者:归游

本文链接:https://www.cnblogs.com/guiyou/p/18690375

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   归游  阅读(22)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起