首页 > 其他分享 >牛客周赛Round 67 个人题解(A~F)

牛客周赛Round 67 个人题解(A~F)

时间:2024-11-11 22:23:38浏览次数:1  
标签:周赛 int 题解 long 牛客 67 define

牛客周赛Round 67 个人题解(A~F)

牛客周赛 Round 67

A-排序危机

题目分析

  • 相对位置不会改变,用三个·字符串模拟即可
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
void solve(){
	int n;cin>>n;
	string s;cin>>s;
	s=" "+s;
	string s1,s2,s3;
	for(int i=1;i<=n;i++){
		if(s[i]>='a' && s[i]<='z') s1+=s[i];
		if(s[i]>='0' && s[i]<='9') s2+=s[i];
		if(s[i]>='A' && s[i]<='Z') s3+=s[i];
	}
	cout<<s1<<s2<<s3<<endl;
}
int main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T=1;
	while(T--) solve();
	return 0;
}

B-小歪商店故事:卷

题目分析

  • 式子变化一下a<b*c/d,注意处理一下整数和小数的区别
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int N=1e5+10;
int ans[N];
void solve(){
	int n;cin>>n;
	for(int i=1;i<=n;i++){
		int a,b,c,d;cin>>a>>b>>c>>d;
		int t=(b*c)/d;
		if(t*d<b*c) ans[i]=a-t;
		else ans[i]=a-t+1;
  	 }
	for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
}
signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T=1;
	while(T--) solve();
	return 0;
}

C-小苯的计算式_牛客周赛 Round 67

题目分析

  • 暴力,因为A+B=C,len(A)+len(B)+len(C)+2=n,枚举A即可算B,然后判断满不满足题目条件即可
  • 一个小trick,计算一个数字的位数可以用log10(x)+1快速求出
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
void solve(){
	int n,c;cin>>n>>c;
	int len=log10(c)+1;
	n=n-len-2;
	int ans=0;
	for(int a=0;a<=c;a++){
		int b=c-a;
		int lena=a?log10(a)+1:1;
		int lenb=b?log10(b)+1:1;
		if(lena+lenb!=n) continue;
		ans++;
	}
	cout<<ans<<endl;
}
signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T=1;
	while(T--) solve();
	return 0;
}

D-K_牛客周赛 Round 67

题目分析

  • 构造题目,首先容易发现当k的最大值只能为n,即所有数都相同,所以当k>n时无解
  • 考虑构造k<n,可以用交替的01串构造,如k=5,n=8,只需01010111
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N=2e5+10;
int a[N];
void solve(){
	int n,k;cin>>n>>k;
	if(k>n){
		cout<<"NO"<<endl;
		return;
	}
	cout<<"YES"<<endl;
	if(k==n){
		for(int i=1;i<=n;i++) cout<<0<<" ";
		cout<<endl;
		return;
	}
	for(int i=1;i<=k+1;i++){
		if(i&1) a[i]=0;
		else a[i]=1;
	}
	for(int i=k+2;i<=n;i++) a[i]=a[i-1];
	for(int i=1;i<=n;i++) cout<<a[i]<<" ";
	cout<<endl;
}
int main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T=1;
	while(T--) solve();
	return 0;
}

E-小苯的区间选数_牛客周赛 Round 67

题目分析

  • 首先题目可以转化为求[l,r]区间取一个数的最大数位和,一道很经典的问题
  • 考虑性质,将l和r每一位都分解开,若两数数字个数相同,则有当a[i]<b[i]时,若对于b来说i之后的位置不全为9,则可以让b[i]-1.后面全都取9,这样一定能满足该数属于[l,r]且数位和不劣于原数(思考一下,因为这一位-1,后面的所有数不全为9的话一定能补上这个减掉的1)
  • 知道这个性质后就可以枚举数位了,为了防止特判,我们可以将两数数字个数不同转化成相同情况,即給l赋值00000
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
void solve(){
	int l1,r1,l2,r2;cin>>l1>>r1>>l2>>r2;
	int l=l1+l2,r=r1+r2;
	string sl=to_string(l);
	string sr=to_string(r);
	int lenl=sl.size(),lenr=sr.size();
	int ans=0,res=0;
	if(lenl!=lenr){
		sl.assign(lenr,'0');
	} 
	for(int i=0;i<lenr;i++){
		if(sl[i]<sr[i]){
			int tmp=(lenr-i-1)*9+(sr[i]-'0'-1)+res;
			ans=max(ans,tmp);
		}
		res+=sr[i]-'0';
	}
	ans=max(ans,res);
	cout<<ans<<endl;
}
signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T;cin>>T;
	while(T--) solve();
	return 0;
}

F-小Z的树迁移_牛客周赛 Round 67

解题思路

  • 树上k-son问题,这里给出dfs序的做法
  • 其实我们需要维护的是对于点u如何快速找到指定层数的点,并求出最大的权值和,首先目标点的层数应该为dep[u]+d
  • 考虑怎么维护子树信息,这里运用到dfs序的方法,我们记录访问一个点的时间为st[i],离开的时间为ed[i],容易发现一个性质,若v在u的子树中那么一定有st[u]<=st[v]<=ed[v]<=ed[u],那么我们可以去预处理每一个点的dfs序,接下来对每一层的点存下对应点的dfs序并排序
  • 然后对于给定点u,我们找到需要到的对应层数,我们要找这一层上在u子树中的点,怎么做呢?我们可以对这一层记录的点的dfs序二分,二分边界即为上一点的条件,这样既可以log时间内找到区间
  • 找到区间之后,我们要做的就是在这个区间内选一个点,使得点u到该点的权值和最大,假设选择的点为v,u的父亲为fa,则权值和为sum[v]-sum[fa],由于u是固定点,所以等价于我们在该区间内选择一个点x,使得sum[x]最大,典型的RMQ问题,这里可以用st表快速维护
  • 具体细节可以看代码的实现
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int N=1e5+10;
struct node{
	int to,w;
};
vector<node> g[N];
int st[N],ed[N],dep[N],sum[N],f[N][20];
int p[N],cnt[N],t[N];//cnt存每一层点个数的前缀和
int n,tot=0;
bool cmp(int x,int y){
	if(dep[x]==dep[y]) return st[x]<st[y];
	return dep[x]<dep[y];
}
//求dfs序,并维护sum与dep数组
void dfs(int u,int fa){
	st[u]=++tot;
	for(auto [v,w]:g[u]){
		if(v==fa) continue;
		dep[v]=dep[u]+1;
		sum[v]=sum[u]+w;
		dfs(v,u);
	}
	ed[u]=tot;
}
void init(){
	for(int j=1;j<19;j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            f[i][j]=max(f[i][j-1], f[i+(1<<(j-1))][j-1]);
        }
    }
}
int query(int l,int r){
	int k=log2(r-l+1);
	return max(f[l][k],f[r-(1<<k)+1][k]);
}
void test(){
	for(int i=1;i<=n;i++) cout<<p[i]<<" ";
	cout<<endl;
	for(int i=1;i<=n;i++) cout<<cnt[i]<<" ";
	cout<<endl;
	for(int i=1;i<=n;i++) cout<<st[i]<<" ";
	cout<<endl;
	for(int i=1;i<=n;i++) cout<<t[i]<<" ";
	cout<<endl;
}
void solve(){
	cin>>n;
	for(int i=1;i<=n-1;i++){
		int u,v,w;cin>>u>>v>>w;
		g[u].push_back({v,w});
		g[v].push_back({u,w});
	}
	dfs(1,0);
	for(int i=1;i<=n;i++) p[i]=i;
	sort(p+1,p+n+1,cmp);
	
	for(int i=1;i<=n;i++){
		int t=dep[p[i]];
		cnt[t]=i;
		f[i][0]=sum[p[i]];
	}
	init();
	for(int i=1;i<=n;i++) t[i]=st[p[i]];
//	test();	
	int q;cin>>q;
	while(q--){
		int u,d;cin>>u>>d;
		int tmp=dep[u]+d;
		int l=lower_bound(t+cnt[tmp-1]+1,t+cnt[tmp]+1,st[u])-t;
        int r=upper_bound(t+cnt[tmp-1]+1,t+cnt[tmp]+1,ed[u])-t;
        if(!cnt[tmp] || r<=l){
        	cout<<-1<<endl;
        }
        else{
        	int ans=query(l,r-1)-sum[u];
        	cout<<ans<<endl;
        }
	}
}
signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T=1;
	while(T--) solve();
	return 0;
}

标签:周赛,int,题解,long,牛客,67,define
From: https://www.cnblogs.com/personaowl/p/18540680

相关文章

  • CSP-J2024 复赛T1(洛谷P11227)题解
    前传作者初赛没过。坐标sd,79分过不了已经适应了。话说这次泄题事件闹得沸沸扬扬,都说各省分数线要降,最后sd降了8分,80。挺逆天的,感觉sd再这样下去一点OIer都要没了。思路桶排思想,用二维数组模拟一整副牌,本来做的时候是怕有重复牌才这样做,事实上不会。ACCode#include<bits/......
  • 《【NOIP2000 基础】计算器的改良》 不全对题解
    温馨提示,本题难度略大,本人写不出来正确代码,文章代码并不对,只是提供一些思路,希望大家能谅解!目录题目描述输入描述输出描述解析完整代码描述NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一......
  • 洛谷题单103数组题解||by红糖
    P1428小鱼比可爱题目描述人比人,气死人;鱼比鱼,难死鱼。小鱼最近参加了一个“比可爱”比赛,比的是每只鱼的可爱程度。参赛的鱼被从左到右排成一排,头都朝向左边,然后每只鱼会得到一个整数数值,表示这只鱼的可爱程度,很显然整数越大,表示这只鱼越可爱,而且任意两只鱼的可爱程度可能一样......
  • [题解](更新中)Refact.ai Match 1 (Codeforces Round 985)
    A-Set显然答案是\(\max(\lfloor\frac{r}{k}\rfloor-l+1,0)\)。点击查看代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intt,l,r,k;signedmain(){ cin>>t; while(t--){ cin>>l>>r>>k; cout<<max(0ll,......
  • 题解:P11262 [COTS 2018] 题日 Zapatak
    https://www.luogu.com.cn/article/i7ajvm8e哈希好题。题意给定一个序列,每次询问给定两个长度相等的区间,问这两个区间是否只有一个数不一样。思路发现我们要求的信息只与数的出现次数有关,自然想到桶。那么如果有两个区间合法,那这两个区间的桶只有两个位置不同且桶内的值均相......
  • 牛客周赛 Round 67 F
    F.小Z的树迁移思路赛事没想出来如何做,可以发现,对于一个节点u,走d步所走的最远距离即为深度为depthu+d且位于u的子树之中的节点距离根节点距离的最大值再减去节点u距离根节点的距离即为结果当我们查询时该如何做?第一步,我们先给每个节点按照dfs序进行编号,这样保证了同一子树的......
  • D题 :K (牛客周赛 Round 67)
    题目链接:题目链接:K题目:分析: 做题一定要认真读题,认真再认真。根据题意可知:极大不同区间的数量是k,但是长度并不一定是k。我看了示例1后,正好3个区间,区间长度都是3,于是认为极大不同区间的长度也是k了。但是题目中没有明确要求,所以极大区间长度不一定为k,只是数量恰好为k。话......
  • P8162 [JOI 2022 Final] 让我们赢得选举 (Let's Win the Election) 题解
    P8162[JOI2022Final]让我们赢得选举(Let'sWintheElection)题解朴素的想法是先抓一部分人,再一起去发表演讲。这样就要按\(b\)的值从小到大排序,枚举选择的一部分\(b\)值,在后面挑选一些最小的\(a\)选择即可。但这样显然是错误的。观察到\(n\le500\),显然是\(O(n^3......
  • 题解:P11062 【MX-X4-T2】「Jason-1」加法
    一道简单的分讨。思路可分成两种情况。当\(a\)和\(b\)同号时:这种情况,显而易见的是\(|a-b|\)的最小值必定是\(|a|,|b|,|a-b|\)之一。当\(a\)和\(b\)异号时:对\((a,b)\)执行欧几里得算法可以将一个变为\(0\),另一个变为\(\gcd(a,b)\)(忽略正负号)。再将\(0\)变......
  • 题解:P10967 [IOI2000] 邮局(原始版)
    思路首先将坐标排序。定义\(dp_{i,j}\)为前\(i\)个村庄放\(j\)个邮局的前\(i\)个村庄的最小距离总和,\(f(i,j)\)表示村庄区间\([i,j]\)内放一个村庄时该区间的总和。转化式易得\(dp_{i}{j}=dp_{k}{j-1}+f(k+1,i),k\in[0,i)\)。则本题的难点就为求\(f(k-1,i)\)。......