NOI模拟赛 4.26

赛时时间分配

读题

-7:40:读T1,感觉T1非常可做,就想了一会儿,大概有了思路(生成函数+隔板法)

-7:50:读完后两题,T2感觉跟线段树有关,其它暂时没有什么想法

T1

-8:35:打T1,一开始发现生成函数部分时间过不去,25min后发现可以直接用前缀和优化

T3

-9:20:打完T3的30pts,感觉下一档分比较麻烦,且有可能会T,先不打

T2

-9:40:打完T2的30pts

-10:00:大概想出了一个T2可行的做法,开始打

-10:35:码完T2

-10:55:拍了会儿T2,感觉问题不大

T3

-11:25:赶完T3的60pts

后记

T1爆零了,,,发现为了降低常数,有一个循环边界改小了QAQ

T1:BZOJ5215商店购物

题目

在 Byteland一共开着\(n\)家商店,编号依次为\(1\)\(n\),其中编号为\(1\)\(m\)的商店有日消费量上限,第\(i\)家商店的日消费量上限为\(w_i\)。Byteasar每次购物的过程是这样的:依次经过每家商店,然后购买非负整数价格的商品,并在结账的时候在账本上写上在这家商店消费了多少钱。当然,他在这家商店也可以什么都不买,然后在账本上写上一个0。这一天, Byteasar日常完成了一次购物,但是他不慎遗失了他的账本。他只记得自己这一天一共消费了\(k\),请写一个程序,帮助 Byteasar计算有多少种可能的账单。

\(1\leq n,k \leq 5*10^7,0\leq w_i\leq300,1\leq m\leq300\)

简要题解

本题可分为带限制和不带限制两部分分别考虑,后半部分即为隔板法。

对于前半部分这种带限制、但取值连续的计数问题,相较生成函数,使用前缀和背包统计答案效率更高。

Tips

前半部分注意循环边界和枚举顺序

	f[0][0]=g[0][0]=1;
	for(int i=1;i<=s[m];++i) g[0][i]=1;
 	for(int i=1;i<=m;++i){
 		for(int j=0;j<=s[m];j++){
 			if(j-w[i]-1>=0)f[i][j]=((g[i-1][j]-g[i-1][j-w[i]-1])%mod+mod)%mod;
 			else f[i][j]=g[i-1][j];
 			if(j>0)g[i][j]=(1LL*g[i][j-1]+1LL*f[i][j])%mod;
			else g[i][j]=f[i][j];
		}
	}

注意n=m时需要特判

T2:BZOJ5216公路建设

题目

在Byteland一共有\(n\)个城市,它们之间计划修建\(m\)条双向道路,其中修建第i条道路的费用为\(c_i\)。Byteasar作为Byteland公路建设项目的总工程师,他决定选定一个区间\([l,r]\),仅使用编号在该区间内的道路。他希望选择一些道路去修建,使得连通块的个数尽量少,同时,他不喜欢修建多余的道路,因此每个连通块都可以看成一棵树的结构。为了选出最佳的区间, Byteasar会不断选择 \(q\)个区间,请写一个程序,帮助 Byteasar计算每个区间内修建公路的最小总费用。
\(n\leq 100,m\leq10^5,q\leq15000\)

简要题解

暴力即为每次Kruscal

发现\(n\)非常小,考虑构建线段树,线段树的每个点上存当前区间的最小生成树中的边,这样相邻区间合并时只影响到数量级为\(O(n)\)的边,由于每个区间内存的边集本身有序,合并时不需要排序,直接归并即可,时间复杂度\(O((m+q\log m)n\log n)\)

tree operator + (tree x,tree y){
	tree res;res.num=0;int j=1;
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=x.num;i++){
		for(;j<=y.num&&e[y.e[j]].w<e[x.e[i]].w;j++)
			if(check(y.e[j]))res.e[++res.num]=y.e[j];
		if(check(x.e[i]))res.e[++res.num]=x.e[i];
	}
	for(;j<=y.num;j++)if(check(y.e[j]))res.e[++res.num]=y.e[j];
	return res;
}
void build(int x,int l,int r){
	if(l==r){
		num(x)=1;
		e(x,1)=l;
		return;
	}
	int mid=(l+r)>>1;
	build(lch,l,mid);
	build(rch,mid+1,r);
	T[x]=T[lch]+T[rch];
}
posted @ 2021-04-26 15:11  Robert_JYH  阅读(62)  评论(0编辑  收藏  举报