Hello 2025 A-D
题解
博主能力有限
A
题意:将0~(n*m-1)的排列,任意放在n×m的二维数组,找到一种放置后的,每行每列没有出现过的最小整数的和,不关心怎么放置,只关心怎么求最大的和
理解对题意后,很容易发现只有0所在的行和列才能使ans增加,而最大的增加方法,假设m>n,那么与0的同一行设置为0-(m-1)的排列,ans+=m,与0的同 一列,那必然是ans+=1,当m<n时,同理
所以最终答案:
ans=max(n,m)+1
B
题意
一个长度为a的数组
给出一次操作:任选区间并删除区间内的所有最小值
操作之前有k次变换,将数组内的数任意变换
求最少操作次数使得数组为空
思路
为了尽可能减少操作次数,那么一次操作就要多删除相同的最小值,所以每次都选择全部的区间
这样选择后,我们的操作次数就是,数组内有多少个不等的数
而操作前的k次变换,可以减少不等的数,进一步使得答案减少
所以根据每个数相同的有多少个进行从小到大排序,从小到大依次减少不等的数,直到k用完
CODE
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
int n,k;
int t;
int top=0;
const int maxn=1e5+10;
int a[maxn];
map<int,int>mp;
void solve(){
cin>>n>>k;
mp.clear();
for(int i=1;i<=n;++i){
int x;
cin>>x;
mp[x]+=1;
}
if(n==1 || k>=n-1){
cout<<1<<endl;
return ;
}
int maxx=0;top=0;
for(auto[x,y]:mp){
a[++top]=y;
}
sort(a+1,a+1+top);
int ans=0;
bool flag=0;
for(int i=1;i<=top;++i){
if(k>=a[i]){
k-=a[i];
}
else {
flag=1;
}
if(flag==1){
ans+=1;
}
}
cout<<ans<<endl;
return ;
}
int main(){
cin>>t;
while(t--){
solve();
}return 0;
}
C
题意
给定区间[l,r],找三个数使得最大,且
思考(官方)
当时看到异或就被吓退了,题没有想象那么难
我们考虑第k个二进制位,如果在该位置上三位中任取1或2个数为0,那么对答案贡献,如果k是l,r最大不同的二进制位,所以答案最多是(可以思考一下为什么这样设置k的原因)
剩下的问题就是如何构造的问题了
官方思路:
找到第一个l和r不同的二进制位设为k,令a为前k-1个二进制位都为1,令b为第k位为1,其它0,这时再这样在区间任取一个不等于a,b的就可以
再讲细点:
a,b已经保证了前k位都不同,这时任取一个区间内的数(不等于a,b),能保证c与不可能在第i个二进制位上都等于a,b,所以必然贡献
CODE
#include<bits/stdc++.h>
using namespace std;
int t;
void solve(){
int l,r;cin>>l>>r;
int k=31-__builtin_clz(l^r);
int a=l|(1<<k)-1,b=a+1,c=a==l?r:l;
cout<<a<<" "<<b<<" "<<c<<endl;
}
int main(){
cin>>t;
while(t--){
solve();
}
return 0;
}
D
向这位博主学习的
思路
我们转化一下题目的条件,那么当区间的端点,为区间的最大最小值,如果是最大值,是最小值,,
如果是最大值,是最小值,,
综上:
修改的操作很符合线段树单点修改的特性,可以用线段树来维护
CODE
#include<bits/stdc++.h>
using namespace std;
#define ls p<<1
#define rs p<<1|1
int n;
const int maxn=8e5+10;
int t,q,x,p;
int m[maxn];
int mina[maxn],minb[maxn];
int maxa[maxn],maxb[maxn];
int ansa[maxn],ansb[maxn];
void push_up(int p){//对于一个节点的最大的ans应该从左儿子的ans和右儿子的ans,左右区间中最大值最小值按照公式相减得到
mina[p]=min(mina[ls],mina[rs]);maxa[p]=max(maxa[ls],maxa[rs]);
minb[p]=min(minb[ls],minb[rs]);maxb[p]=max(maxb[ls],maxb[rs]);
ansa[p]=max(max(ansa[ls],ansa[rs]),maxa[rs]-mina[ls]);
ansb[p]=max(max(ansb[ls],ansb[rs]),maxb[ls]-minb[rs]);
return ;
}
void build(int p,int l,int r){
if(l==r){
mina[p]=maxa[p]=m[l]-l;
minb[p]=maxb[p]=m[l]+l;
ansa[p]=ansb[p]=0;
return ;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
push_up(p);
}
void update(int p,int l,int r,int po,int ua,int ub){//单点更新
if(l==r){
mina[p]=maxa[p]=ua;
minb[p]=maxb[p]=ub;
ansa[p]=ansb[p]=0;return ;
}
int mid=(l+r)>>1;
if(po<=mid) update(ls,l,mid,po,ua,ub);
else update(rs,mid+1,r,po,ua,ub);
push_up(p);
}
void solve(){
cin>>n>>q;
for(int i=1;i<=n;++i) cin>>m[i];
build(1,1,n);
cout<<max(ansa[1],ansb[1])<<"\n";
while(q--){
cin>>p>>x;
update(1,1,n,p,x-p,p+x);
cout<<max(ansa[1],ansb[1])<<"\n";
}return ;
}
int main(){
cin>>t;
while(t--){
solve();
}
return 0;
}
本文作者:归游
本文链接:https://www.cnblogs.com/guiyou/p/18666921
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步