牛客xiao白月赛39题解

比赛:牛客小白月月赛39

比赛链接

题解+视频

本人小记+代码:

A题:(签到)

  1. 向量(x,y)+(x0,y0)=(x+x0,y+y0)
  2. 向量平行条件:(满足其一即可,不要混淆在一起)
    1、a=λb(λ!=0),则a∥b。
    2、设a(x1,y1)、b(x2,y2),若x1y2=y1x2,则a∥b

C题:
看视频讲解:

#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
	int n;scanf("%d",&n);
	int A=0,B=0,a,b;
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%d %d",&a,&b);
		ans+=max(0,min(a,b)-max(A,B)+(A!=B));
		A=a,B=b;
	}
	printf("%lld\n",ans);
	return 0;
}
/*
我的理解:

细细琢磨琢磨这三句话: 
a b序列分别遵循从小到大,且初A=0,b=0; 
情况2:当A=at时,让B直接加到与bt相等
情况3:当B=bt时,让A直接加到与at相等

i从(1,n)遍历,
只需考虑当前A变a[i],B变b[i]后,ans需要加多少

为何:
若a[i],b[i]满足情况2或3,那A和B最后铁定要变成A=a[i],b[i];
若不满足,考虑情况4:(A,B)其一加1,
加多少次才会满足情况2或3呢,不清楚,那为何不直接A=a[i],b[i];

为何可以从1逐步遍历到n呢?
还是因为那三句话:
A和B只能逐步变大,恰数列a,b也是从小到大。
比如:
当前A=3,B=9。怎么得到A=3,B=9呢,肯定源于比它小的a[i]和b[i]得到
若A,B想再变大,肯定要遍历不能小于当前A,B的a[i]和b[i].

因此题意转变为:
当A,B变成a[i]和b[i]时,ans需要加多少次
A       B
a[i]   b[i] 
肯定A<=a[i],B<=b[i]
不确定:A和B,a[i]和b[i]的大小;
不确定:A和b[i],B和a[i]的大小;即max(A,B)和min(a[i],b[i])大小不确定 
A-->a[i]
B-->b[i]

公共部分为:[max(A,B),min(a[i],b[i])]

因此:ans+=max((max(A,B),min(a[i],b[i])+		(A!=B)),0); 
*/

G题:

看视频讲解(讲的不是很明白,本人对树状数组理解有欠缺,代码正确,但不太明白)

#include<bits/stdc++.h>
using namespace std;
const int N=3e6;
const int maxn=3e6+110;
int res[maxn],tr[maxn];
bool book[maxn];
int p[maxn],pmin[maxn],cnt;
/*
book,p,cnt为欧拉素数筛使用 
pmin[i]表示i的最小质因数为pmin[i]
算了,下面的理解也应该不对 
Query(k)表示1~N中<=k的质数的个数
可利用树状数所构造的数据结构求前缀和[1,x]的前缀和,即Query(x).
该前缀和为1~N中最小质因数为2的个数 + 1~N中最小质因数为3个数 + ... 
*/
struct Node{
	int n,k,id;
	bool operator<(const Node &b)const
	{
		if(n==b.n)	return k<b.k;
		else		return n<b.n;
	}
}q[maxn];
void Get_prime()
{
	cnt=0;book[1]=1;
	for(int i=2;i<=N;i++)
	{
		if(!book[i])
			p[++cnt]=i,pmin[i]=i;
		for(int j=1;j<=cnt&&p[j]<=N/i;j++)
		{
			book[i*p[j]]=1;
			pmin[i*p[j]]=p[j];
			if(i%p[j]==0)	break;
		}
	}
}
int lowbit(int x){ return x&(-x);}
void add(int x,int d)
{
	while(x<=N)
	{
		tr[x]+=d;
		x+=lowbit(x);
	}
}
int Query(int x)
{
	int ans=0;
	while(x>0)
	{
		ans+=tr[x];
		x-=lowbit(x);
	}
	return ans;
}
int main()
{
	Get_prime();
	int m;scanf("%d",&m); 
	for(int i=1;i<=m;i++)
	{
		int n,k;scanf("%d %d",&n,&k);
		q[i]={n,k,i};
	}
	sort(q+1,q+1+m);//按照n从小到大排序
	int p=1;
	for(int i=1;i<=m;i++)
	{ 
		while(p<q[i].n)
			add(pmin[++p],1); 
		res[q[i].id]=q[i].n-1-Query(q[i].k-1);
		//-1是1~n中1不算
		//Query(k)求的是在[1,N]中最小质因子>=k的数有多少个
		//tr[x]表示区间[x-lowbit(x)+1,x] 
	}
	for(int i=1;i<=m;i++)
		printf("%d\n",res[i]);
	return 0;
}	
/* 
1
8 2
for(int i=1;i<=10;i++)
	printf("^^^%d\n",Query(i));
*/

H题:
视频讲解很详细

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e6+110;
const ll INF=0x3f3f3f3f3f3f3f3f;
ll p[N],s[N],pre[N],suf[N];
int main()
{
	int n,d;scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&p[i]);
		s[i]=p[i];
	}
	pre[0]=0;
	for(int i=1;i<=n;i++)
	{
		d=p[i];
		pre[i]+=pre[i-1]+d;
		p[i+1]=max(0ll,p[i+1]-d);
		p[i+2]=max(0ll,p[i+2]-d);
	}
	suf[n+1]=0;
	for(int i=n;i>=1;i--)
	{
		d=s[i];
		suf[i]+=suf[i+1]+d;
		s[i-1]=max(0ll,s[i-1]-d);
		s[i-2]=max(0ll,s[i-2]-d);
	}
	if(n<=2)
		printf("0\n");
	else
	{
		ll ans=INF;
		for(int i=2;i<=n;i++)
			ans=min(ans,pre[i-2]+suf[i+1]);
		printf("%lld\n",ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值