2022河南萌新联赛第(七)场:南阳理工学院ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛牛客竞赛OJ (nowcoder.com)

2022河南萌新联赛第(七)场:南阳理工学院ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛牛客竞赛OJ (nowcoder.com)

1.B-龍_2022河南萌新联赛第(七)场:南阳理工学院 (nowcoder.com)

每次操作1刚好可以消除一次操作2,考虑n个团块,最后总共只需要n次操作。那就看a,b中谁更小我就操作谁更多次。

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
string s;
int n,a,b,x,cnt;
void slove(){
   cnt=0;
cin>>n>>a>>b>>x;
   cin>>s;
int la='1';
for(int i=0;i<n;i++){
if(la!=s[i]&&s[i]=='0') cnt++;
la=s[i];
}
   if(cnt==0){
       cout<<"Yes"<<endl;
       cout<<x<<endl;
       return;
  }
int ans=(cnt-1)*min(a,b)+b;
if(ans<=x){
cout<<"Yes"<<endl;
cout<<x-ans<<endl;
}
else{
cout<<"No"<<endl;
}
}
signed main(){
int t;
cin>>t;
while(t--){
slove();
}
return 0;
}

2.C-机智的我_2022河南萌新联赛第(七)场:南阳理工学院 (nowcoder.com)

感觉是个玄学题。

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
int n,k;
signed main(){
cin>>n>>k;
if(k) cout<<"Why not";
else cout<<"Whatever";
return 0;
}

3.D-疯狂星期八_2022河南萌新联赛第(七)场:南阳理工学院 (nowcoder.com)

很明显倒着取是更优的。我们考虑倒着取最多之只能取100个。所以我们直接考虑开一个100体积的01背包,只要花费小于m就代表取当前这么多物品时有可能的。

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
const int N=1e5+100;
int n,m;
int f[110];//背包体积只有100//只要此时的花费是小于m的即可
int w[N];
signed main(){
cin>>n>>m;
for(int i=1;i<=105;i++) f[i]=m+1;
for(int i=1;i<=n;i++) cin>>w[i];
f[0]=0;
for(int i=n;i>=1;i--){
for(int j=100;j>=1;j--){
f[j]=min(f[j],f[j-1]+w[i]+(j-1)*i);
}
}
for(int i=100;i>=0;i--){
if(f[i]<=m){
cout<<i<<endl;
return 0;
}
}
return 0;
}

4.F-数对_2022河南萌新联赛第(七)场:南阳理工学院 (nowcoder.com)

思考一下&值什么时候大于^值,只要两个数最高位1时相同位置即可。所以问题就转化成立区间内有多少对最高位1位置相同。由于时相等,所以两数都是0也可以。将数组转化成存最高位1出现的位置,2^0存1,最后只需要统计区间内相同数的对数即可。

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
&值大与^则需要考虑两个数最高位1时相同位置即可
都是0也可以
然后只要找区间内出现相同值的对数即可
只有0-31这几个数
*/
const int N=1e5+100;
int n,m;
int a[N];
int sum[N][40];
void change(int &x){
int tot=0;
int ans=0;
while(tot<31){
if(x&1) ans=tot+1;
tot++;
x>>=1;
}
x=ans;
}
signed main(){
cin>>n>>m;
fel(i,1,n){
cin>>a[i];
change(a[i]);
      // cout<<a[i]<<" ";
}
   //cout<<endl;
for(int i=1;i<=n;i++) sum[i][a[i]]=1;
   for(int i=0;i<=31;i++){
       for(int j=1;j<=n;j++){
           sum[j][i]+=sum[j-1][i];
      }      
  }
while(m--){
int x,y;
int ans=0;
cin>>x>>y;
for(int i=0;i<=31;i++){
ans+=(sum[y][i]-sum[x-1][i])*(sum[y][i]-sum[x-1][i]-1)/2;
}
cout<<ans<<endl;
}
return 0;
}

5.G-小明不希望太简单_2022河南萌新联赛第(七)场:南阳理工学院 (nowcoder.com)

最多那个字母的空肯定是最多的,所以直接考虑插空到出现次数最多的那个字母当中即可。

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
第一个字符所形成的空肯定是最多的
只要在这些空塞下所有字符即可
*/
const int N=1e5+100;
string s;
struct node{
char out;
int w;
}a[30];
vector<char>ans[N];
bool cmp(node a,node b){
return a.w>b.w;
}
signed main(){
cin>>s;
for(auto i:s){
a[i-'a'].w++;
a[i-'a'].out=i;
}
sort(a,a+26,cmp);
int cnt=0,mod=a[0].w;
for(int i=0;i<26;i++){
while(a[i].w){
ans[cnt].pb(a[i].out);
a[i].w--;
cnt++;
cnt%=mod;
}
}
for(int i=0;i<mod;i++){
for(auto j:ans[i]){
cout<<j;
}
}
return 0;
}

6.H-防风台_2022河南萌新联赛第(七)场:南阳理工学院 (nowcoder.com)

直接考虑从大到小排序,看去掉当前点是否可以,如果不可以了这个点就是答案。

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
感觉是考虑n和m中比较大的mx
考虑对原数组排个序
如果,然后用一个行和一个列数组存下每一个属于这个行的元素
*/
const int N=1e6+100;
int h[1100],l[1100],n,m;
struct node{
int h,l,w;
}a[N];
bool cmp(node a,node b){
return a.w>b.w;
}
signed main(){
cin>>n>>m;
int cnt=0;
fel(i,1,n){
fel(j,1,m){
cin>>a[++cnt].w;
a[cnt].h=i;
a[cnt].l=j;
h[i]++;
l[j]++;
}
}
sort(a+1,a+1+cnt,cmp);
for(int i=1;i<=cnt;i++){
auto[x,y,z]=a[i];
h[x]--,l[y]--;
if(h[x]==0||l[y]==0){
cout<<z<<endl;
return 0;
}
}
return 0;
}

7.J-最短路_2022河南萌新联赛第(七)场:南阳理工学院 (nowcoder.com)

最小生成树,然后在最小生成树上面走即可。

为什么最小生成树就一定是保证最长的那条路最短呢?

考虑最小生成树生成的方式,选择新边时,肯定选择的时最短的边。其他边走的肯定时更长的。

官方解释:
最小生成树的Kruskal算法建树过程是将边从小到大排序,然后从小到大选择这些边

开始时有n个连通块(n个不相连的点),每次选择一个边就会连接两个连通块为同一个,总连通块数量将-1,所以最小生成树只有n-1个边

而对于这个题,选择新的边建最小生成树的时候,一个点可以在一个连通块内任意移动(因为之前已经连接的边都是比当前边小)

那么不可能再选择同一连通块的点与点之间的边(选了也不会走),只会从小到大地选择非连通的连通块,也就是最小生成树的Kruskal算法建树过程

所以最小生成树对于每个点到点之间,都是局部最优的走法
#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
最小生成树建树即可
然后每次深搜
在形成最小生树的时候形成边
*/
const int N=1e5+100;
struct edge{
int from,to,w;
friend bool operator<(const edge a,const edge b){
return a.w<b.w;
}
}b[N];
struct node{
int id,w;
};
int n,m,q,fa[N],dis[N];
vector<node>a[N];
int find(int x){
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
void dfs(int x,int f){
for(auto [id,w]:a[x]){
if(id==f) continue;
dis[id]=max(dis[x],w);//能到的点和这条路
dfs(id,x);
}
}
signed main(){
IOS
cin>>n>>m;
fel(i,1,n) fa[i]=i;
fel(i,1,m)
cin>>b[i].from>>b[i].to>>b[i].w;
sort(b+1,b+1+m);
for(int i=1;i<=m;i++){
auto[x,y,w]=b[i];
if(find(x)!=find(y)){
a[x].pb({y,w});
a[y].pb({x,w});
fa[find(x)]=find(y);
}
}
cin>>q;
while(q--){
int x,y;
cin>>x>>y;
memset(dis,0,sizeof(dis));
dfs(x,x);
cout<<dis[y]<<endl;
}
return 0;
}

8.K-工程师CY_2022河南萌新联赛第(七)场:南阳理工学院 (nowcoder.com)

二分。

考虑二分l。如何check呢?我们考虑贪心的放电线。为了最大的利用每个电线杆的作用,我们尽量将左边的钢丝往左边放。具体操作看代码。

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
二分
也就是考虑我每次二分l
考虑尽可能的利用每一个点
所以尽量将左边的钢丝往左边放
这起码的有2000分了
确实没想到
*/
const int N=1e5+100;
int n,k;
int a[N],dp[N];//i位置放的钢丝数量
bool check(int x){
for(int i=1;i<=x;i++) dp[i]=a[i];//距离0位置距离小于mid的点都可以放钢丝
int l=1;
for(int i=x+1;i<=n;i++){
dp[i]=0;
while(i-l>x) l++;//激励超过l的用不了了
while(dp[i]<a[i]&&l<i){
if(dp[l]+dp[i]<=a[i]){
dp[i]+=dp[l];
dp[l]=0;
l++;
}
else{
dp[l]-=a[i]-dp[i];
dp[i]=a[i];
}
}
}
int sum=0;
l=n+1-x;
for(int i=l;i<=n;i++) sum+=dp[i];
return sum>=k;
}
signed main(){
IOS
cin>>n>>k;
fel(i,1,n){
cin>>a[i];
}
int l=1,r=n+1,ans=n+1;
while(l<=r){
int mid=l+r>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans<<endl;//ans肯定存在
return 0;
}

9.L-Oo___2022河南萌新联赛第(七)场:南阳理工学院 (nowcoder.com)

考虑内切外切两种情况即可。注意重合不算相切(坑点)。

#include<bits/stdc++.h>
using namespace std;
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define feh(i,x,y) for(int i=x;i>=y;i--)
#define int long long
#define pb push_back
#define IOS cin.tie(0)->sync_with_stdio(false);
#define inf 0x7fffffff
#define endl "\n"
/*
内切外切
内切ad-bc=0,此时切x的点时重合的
外切ad-bc=+-1
easy题
*/
int a,b,c,d;
void slove(){
cin>>a>>b>>c>>d;
int t=a*d-b*c;
   if(t==0&&b==d) cout<<"NO"<<endl;
   else if(t==-1||t==0||t==1) cout<<"YES"<<endl;
   else cout<<"NO"<<endl;
}
signed main(){
   IOS
int t;
   cin>>t;
while(t--){
slove();
}
return 0;
}
 
posted @   silky__player  阅读(68)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示