牛客练习赛34(ABC)

被舍友安利剑三,结果练习赛只做了3题,难道后天csp300分稳了,开心。

一:A little w and Exchange

题目:不知道你听没听说过这样一个脑筋急转弯。

2元可以买一瓶汽水(玻璃瓶装的),因为瓶身是玻璃瓶的比较贵,所以两个瓶身可以换一瓶汽水。你现在有4元钱,问最多能喝到多少瓶汽水?

答案是4瓶。一开始先用4元钱买两瓶汽水喝掉,再用这两瓶的汽水的瓶身换一瓶喝到,最后还剩一个瓶身,这个时候再朝小卖部的老板借一个瓶身。换一瓶汽水喝掉之后再还给他一个瓶身。

现在问题来了,一开始你有n元钱,然后你最多可以向老板借一个瓶身(注意要还的),问你最多能喝到多少瓶汽水?

思路:大水题,令g(n)为有n元钱可以喝到得汽水数量,则g(n)=g(n-2)+2,再奇偶合并一下,则g(n)=n-(n&1)。

二:B little w and Sum

略。

三:C little w and Segment coverage

题目:小w有m条线段,编号为1到m。

用这些线段覆盖数轴上的n个点,编号为1到n(1<=n<=100000)。

第i条线段覆盖数轴上的区间是L[i],R[i]。

覆盖的区间可能会有重叠,而且不保证m条线段一定能覆盖所有n个点。

现在小w不小心丢失了一条线段,请问丢失哪条线段,使数轴上没被覆盖到的点的个数尽可能少,请输出丢失的线段的编号和没被覆盖到的点的个数。如果有多条线段符合要求,请输出编号最大线段的编号(编号为1到m)。

思路:先用差分数组计算每个点被覆盖得次数,然后线段树或者什么什么区间查询就行。

代码:

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int N=1e5+5;

P a[N];
int num[N<<2]={0},p[N];
void build(int l,int r,int rt){
	if(l==r){
		num[rt]=p[l]==1;
		return;
	}
	int m=(l+r)>>1;
	build(lson);
	build(rson);
	num[rt]=num[rt<<1]+num[rt<<1|1];
}
int query(int ql,int qr,int l,int r,int rt){
	if(ql<=l&&r<=qr) return num[rt];
	int m=(l+r)>>1,ans=0;
	if(ql<=m) ans+=query(ql,qr,lson);
	if(m<qr) ans+=query(ql,qr,rson);
	return ans;
}
int main(){
	int n,m,l,r;
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++){
		scanf("%d%d",&a[i].first,&a[i].second);
		p[a[i].first]++,p[a[i].second+1]--;
	}
	int s=0;
	for(int i=1;i<=n;i++){
		p[i]+=p[i-1];
		if(!p[i]) s++;
	}
	build(1,n,1);
	int ans=n+1,t;
	for(int i=0;i<m;i++){
		int tt=query(a[i].first,a[i].second,1,n,1);
		if(tt+s<=ans){
			ans=tt+s;
			t=i+1;
		}
	}
	printf("%d %d\n",t,ans);
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/Advancingxq/p/10122184.html
今日推荐