被舍友安利剑三,结果练习赛只做了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; }