codeforces爆做

从现在起,最后几天刷题,从7月1日开始复习以前做过的题目和考试,整理模板和经典题目


622E 贪心

考虑每个1的子节点,把子树中所有叶子节点按深度排序,那么贪心的让深度小的叶子先上去

dp[i]表示i最快用多久到根

dp[i]=max{dp[i-1]+1,dep[i]}

最后这一个转移方程没有想到啊,挺巧妙的


666C 组合+dp

容易发现,答案与字符串的构成无关,只与字符串的长度有关

设m为模板串的长度,n为匹配串的长度

ans=∑C(i-1,m-1)*25^(i-m)*26^(n-i)

以最靠前的子序列为标准,枚举最后一个点的位置i,在前面的i-1个地方选m-1个来填数,其中s[i]和s[i+1]之间,所有的数都不等于s[i+1],最后一个点之后的字母可以随意选择

但是暴力是O(mn)的,如何优化?

当长度小于等于sqrt(n)时,预处理出答案

当长度大于sqrt(n)时,这样的串不会超过sqrt(n)个,每次暴力递推长度为i的方案数

复杂度O(nsqrt(n))


660E 组合数学

与上题相似,不考虑长度为0的子序列,通过枚举最后一个点的位置,确定包含每个长度的个数

ans=∑m^i*m^(n-j)*(m-1)^(j-i)*C(j-1,i-1) (1<=i<=n,i<=j<=n)

=∑m^(n-j+i)*(m-1)^(j-i)*C(j-1,i-1)
改变枚举对象,s=n-j+i(1<=s<=n)
=∑m^s*(m-1)^(n-s)*∑C(n-s+i,i) (0<=i<s)
有一个公式∑C(r+k,k)(k<=n)=C(r+n+1,r+1)
∑C(n-s+i,i)=C(n,s-1)
ans=∑m^s*(m-1)^(n-s)*C(n,s-1)

O(n)直接计算即可


671C 奇怪的计数问题

考虑计算Hi表示答案小于等于i的(l,r)对数

对于确定的i,容易发现f(l,r)随着r增加,单调递减

对于每一个l,维护nxt[l]表示最小的位置满足f(l,nxt[l])<=i

Hi=∑n-nxt[l]+1=n(n+1)-∑nxt[l]

倒序枚举i,当i+1变成i时,考虑nxt[l]的变化

答案等于i时,满足至少存在两个i的倍数

要使答案小于i,则必须满足最多只存在一个i的倍数

记四个数l1,l2,r1,r2分别表示所有数中是i的倍数的最靠左的数、次靠左的数、最靠右的数、次靠右的数,[l,r]表示当前区间

若l<l1,则nxt[l]=r2

若l1<=l<=l2,则nxt[l]=r1

若l>l2,则nxt[l]=n+1

对于确定的l,容易发现随着i减小,nxt[l]单调递增,所以可以转化成三个区间取max的操作

由于nxt序列是单调的,所以区间取max等价于区间赋值,可以用线段树维护

复杂度O(nsqrt(n)+nlogn)


677E  奇技淫巧

主要考察的是旋转坐标系的技巧,横竖的非常好处理

斜着的就把矩阵旋转45°,(x,y)-->(x+y,x-y)

如何判断两个数的大小?取个log判一下


675E  dp+贪心

dp[n]=0

dp[i]=max{dp[j]-(a[i]-j+1)+(n-i)}

可以证明在dp[j]的计算中,[j,a[i]]中所有的点到j的距离一定是1

然后线段树优化dp


659E  贪心

不同联通块之间肯定不影响,同一个联通块中,如果是一棵树,则只有根节点计入答案,否则选择一个在环里的点当做根,对答案贡献为0


670F  构造

乱七八糟的题,除了细节多,没有别的。

先要找出一个长度合适的数列,实际最多只可能有6种长度,找到长度最小的即可。

然后,问题变成了给你一个字符串和一堆数字,要你拼成一个字典序最小的串

如果字符串以0开头,那么首先找一个非0的数放在开始,然后把0都加进去,然后加入字符串,然后升序向内加数

如果字符串非0开头,那么两种情况:

1、把字符串放到开头,升序加数

2、找一个非0的数放在开始,升序加数的过程中,把字符串加到合适的位置


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值