牛客白月赛29题解

Posted 辉小歌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客白月赛29题解相关的知识,希望对你有一定的参考价值。

https://ac.nowcoder.com/acm/contest/8564

目录

进攻【贪心+二分】


前缀最大数组,然后二分找。

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;

const int N=1e6+10;
const int mod=1e9+7;

int n,m,a[N],maxv[N],b[N],x[N],y[N];

struct nodeint x,y;;
vector<node>ve;
map<int,int>mp;

int main(void)
 
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=m;i++) cin>>x[i];
	for(int i=1;i<=m;i++) cin>>y[i];
	for(int i=1;i<=m;i++) mp[x[i]]=max(mp[x[i]],y[i]);
	for(auto i=mp.begin();i!=mp.end();i++) 
		ve.push_back(i->first,i->second);
	maxv[0]=max(ve[0].y,0);
	for(int i=1;i<ve.size();i++) maxv[i]=max(maxv[i-1],ve[i].y,0);
	for(int i=0;i<ve.size();i++) b[i]=ve[i].x;
	int k=ve.size();
	LL ans=0;
	for(int i=1;i<=n;i++)
	
		int index=lower_bound(b,b+k,a[i])-b;
		index--;
		if(index<0) continue;
		ans+=maxv[index];
	
	cout<<ans;
	return 0;

二进制【位运算 思维】


位运算的题目大部分都是只需考虑各个位即可。
本题,只需操作三次即可。与,或,异或个一次。

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int> pii;
vector<pii>ve;
int main(void)

	int n; cin>>n;
	for(int i=0;i<n;i++)
	
		int a,b; cin>>a>>b;
		ve.push_back(a,b);
	
	int a=(1<<20)-1,b=0,c=0;//与 或 异或  a=全1 目的是任意一个数与都是本身 
	for(int i=0;i<20;i++)
	
		int w1=0,w2=1;//当前位是0 当前位是1
		for(int j=0;j<ve.size();j++) 
		
			int op=ve[j].x,w=ve[j].y;
			int now=0;
			if(w>>i&1) now=1;
			if(op==1)
			
				w1=w1&now;
				w2=w2&now;
			
			if(op==2)
			
				w1=w1|now;
				w2=w2|now;
			
			if(op==3)
			
				w1=w1^now;
				w2=w2^now;
			
		
		if(w1==0&&w2==0) a-=(1<<i); //说明不管是啥结果都是0 故该为一定与一个0 
		if(w1==0&&w2==1) ;//说明啥都不变,故各个操作也不变 
		if(w1==1&&w2==0) c+=(1<<i);  //说明我们该位看好取反了  故异或位一定为1
		if(w1==1&&w2==1) b+=(1<<i);  //一定或一个1 
	
	cout<<3<<endl;
	cout<<1<<" "<<a<<endl;
	cout<<2<<" "<<b<<endl;
	cout<<3<<" "<<c<<endl; 
	return 0;

积木【构造】

构造题咕咕了。

种树【贪心】


贪心,先用完小的再用大的。

#include<bits/stdc++.h> 
using namespace std;
const int N=1e5*5+10;
int n,m,ans,l[N],r[N],w[N],d[N];
void dfs(int u,int d)

    if(!l[u])//不是叶子
	
        if(d<=m) ans=max(ans,w[u]);//且可以是大剪刀
        return;     
    
    dfs(l[u],d+1),dfs(r[u],d+1);

int main(void)

	cin>>n;
	for(int i=1;i<=n;i++)
	
		int a,b; cin>>a>>b;
		l[i]=a,r[i]=b;
	
	for(int i=1;i<=n;i++) cin>>w[i];
	for(int i=1;i<=n;i++) if(l[i]&&r[i]) m++;
    m=(m+1)/2;//大剪刀
	dfs(1,0);
	cout<<ans<<endl; 
	return 0;

考试

#include<bits/stdc++.h>
using namespace std;

const int N=1e6+10;
const int mod=1e9+7;

int n,m,a[N],b[N];

int main(void)
 
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	int cnt=0;
	for(int i=1;i<=n;i++) if(a[i]==b[i]) cnt++;//相等的
	int ans=min(cnt,n-m)+min(n-cnt,m);
	cout<<ans;
	return 0;

项链【双链表模拟】

咕咕了

涂色

#include<stdio.h>
int main(void)

    int n,sum=0;
    while( scanf("%d",&n) != EOF )
    
        sum=n+1;
        printf("%d\\n",sum%998244353);
    

圆【圆的相切】

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long int LL;
int main(void)
 
	int t; cin>>t;
	while(t--)
	
		LL x1,y1,r1,x2,y2,r2; cin>>x1>>y1>>r1>>x2>>y2>>r2;
		LL len=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
		if(len<(r1-r2)*(r1-r2))
		
			puts("NO");
			continue;
		
		if(len<=(r1+r2)*(r1+r2)) puts("YES");
		else puts("NO");
	
	return 0;

/*
1、两圆外离。两圆距离大于两圆半径之和;

2、两圆外切。两圆距离等于两圆半径之和;

3、两圆相交。两圆距离小于两圆半径之和;

4、两圆内切。两圆距离等于大圆半径减小圆的半径;

5、两圆内含。两圆距离小于大圆的半径减小圆的半径。

*/

修改【思维 构造最小生成树】


#include<bits/stdc++.h>
using namespace std;
typedef long long int LL; 
const int N=1e5*5+10;
int p[N],n,m; 
struct nodeint a,b,c;;
bool cmp(node a,node b)return a.c<b.c;
vector<node>ve;
int find(int x)

    if(x!=p[x]) p[x]=find(p[x]);
    return p[x];

void solve()

	for(int i=1;i<=n;i++) p[i]=i;
	sort(ve.begin(),ve.end(),cmp);
	LL sum=0;
	for(int i=0;i<ve.size();i++)
	
		int a=ve[i].a,b=ve[i].b,c=ve[i].c;
        if(find(a)==find(b)) continue;
		p[find(a)]=find(b);
		sum+=c;
	
    map<int,int>mp;
    for(int i=1;i<=n;i++) mp[find(i)]++;
	if(mp.size()==1) cout<<sum;
	else puts("-1");

int main(void)

	cin>>n>>m;
	for(int i=1;i<=m;i++)
	
		int a,b,c; cin>>a>>b>>c;
		ve.push_back(a,b+1,c);
	
	solve();
	return 0;

克隆【欧拉序列】



就是求欧拉序列,然后分组输出即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
int n,m,k;
int h[N],e[N],ne[N],idx,len,ans[N];
vector<int>ve;
stack<int>st;
map<int,int>mp;
void add(int a,int b)

	e[idx]=b,ne[idx]=h[a],h[a]=idx++;

void dfs(int u)

	mp[u]=1;
	ans[++len]=u; 
	for(int i=h[u];i!=-1;i=ne[i])
	
		int j=e[i];
		if(mp[j]) continue;
		dfs(j);
		ans[++len]=u;
	
	return;

int main(void)

	memset(h,-1,sizeof h);
	cin>>n>>m>>k;
	while(m--)
	
		int a,b; cin>>a>>b;
		add(a,b),add(b,a);
	
	dfs(1);
	puts("YES");
	int w=ceil(2.0*n/k);
	queue<int>q;
	for(int i=1;i<=len;i++) q.push(ans[i]);
	for(int i=1;i<=k&&q.size();i++)
	
		int temp=min(w,(int)q.size());
		cout<<temp;
		for以上是关于牛客白月赛29题解的主要内容,如果未能解决你的问题,请参考以下文章

牛客白月赛8题解

牛客白月赛4 题解

牛客白月赛11题解

牛客白月赛12题解

牛客白月赛10题解

牛客白月赛14题解