杂题
废弃
CF61E
\(f_{i,j}\) 表示以 \(i\) 为结尾,长度为 \(j\) 的严格下降子序列的数量。
则 \(f_{i,j}= \sum_{1 \le k < i,a_k>a_i}f_{k,j-1}\)。
用树状数组优化,所以要先离散化。
时间复杂度 \(\mathcal{O}(n \log n)\)。
优越性在于可以扩展到长度为 \(m\) 的子序列的情况。
ABC295E
\(\sum_{i=1}^N \sum_{j=1}^i F(i)=\sum_{i=1}^N \sum_{j=i}^N F(j)\)。
所以 \(E(A_k)=\sum_{i=1}^m i \times P(A_k=i)=\sum_{i=1}^m \sum_{j=1}^i P(A_k=i)=\sum_{i=1}^m \sum_{j=i}^m P(A_k=j)=\sum_{i=1}^m P(A_k \ge i)\)。
那么现在枚举 \(i\),计算 \(P(A_k \ge i)\),只需满足 \(Q(i) \ge n-k+1\) 即可,其中 \(Q(i)\) 表示 \(\ge i\) 的数的个数。
假设原序列中有 \(x\) 个 \(0\),有 \(y\) 个 \(\ge i\) 的数。若 \(y \ge n-k+1\),则 \(P(A_k \ge i)=1\),否则考虑枚举 \(j \in[n-k+1-y,x]\),表示有 \(j\) 个 \(0\ge i\),则这个概率为 \(\binom{x}{j} \times (\frac{m-i+1}{m})^j \times(\frac{i-1}{m})^{x-j}\)。
P3572 [POI2014] PTA-Little Bird
设 \(f_i\) 表示飞到第 \(i\) 棵树的最小体力。
\(f_i=\min_{\max\{i-k,1\} \le j<i}\lbrace f_j+[d_j \le d_i]\rbrace\)
同样的 \(f_i\),\(a_j\) 越大越优,直接单调队列送走。
CF66E
断环为链,设 \(SA,SB\) 分别为 \(a,b\) 的前缀和数组。
顺时针时,对于一个 \(x\): $\forall x \le i \le n+x,SA_i-SB_i\ge SA_{x-1}-SB_{x-1} $
\(SA_{i}-SA_{x-1} \ge SB_{i}-SB_{x-1}\)
这个条件也就是说:\(SA_{x-1}-SB_{x-1}\) 是这一段的最小值。
逆时针时,对于一个 \(x\):\(\forall x \le i \le n+x,SA_{n+x}-SB_{n+x}\ge SA_{i-1}-SB_{i-1}\)
就是说:\(SA_{n+x}-SB_{n+x}\) 是 \([x-1,n+x-1]\) 的最大值。
st 表维护即可。
CF437C
很巧妙啊。
这个与点相邻且没被删除的所有点不太好办啊,考虑不删点,改成删边,反正最后所有边都被删了。
这样一个点涉及的多个变化被转化为了一条边涉及的一个变化。那么让每条边的权值为它两个端点点权的最小值即可。
正确性可以考虑到将点从大到小删,那么每条边都能达到最小权值。
P9329 [JOISC 2023 Day1] Two Currencies
尽量用银币,银币尽量在 \(c\) 小的时候用。
二分能用多少银币,那么只需要实现对一条链查询前 \(k\) 小的数之和。主席树做树上差分即可。
CF266E
\((i+(1-l))^k=\sum_{i=0}^k \binom{k}{i}i^i(1-l)^{n-i}\),所以原式就是求
需要维护的是区间每个点乘上一个系数的和,这个系数可以预处理。
时间复杂度 \(\mathcal{O}(mk \log n)\)。
CF1850D
如果一个点,距离它最远的点距离 \(<k\),那么没救,它是孤立点。
否则,距离它最远的点距离 \(\ge k\),那么直径 \(\ge k\),那么这些都通过直径的端点连了起来,就是一个连通块。
CF1109E
肯定要求逆元,那就是 \(ax \equiv 1( \bmod\bm p)\),那么改写为 \(ax+py =1\),有解当且仅当 \(\gcd(a,p)=1\)。那么 \(\gcd(a,p) \neq 1\) 的时候就没有逆元了,那怎么办呢。对 \(P\) 做质因数分解,那么 \(\gcd(a,p)\neq 1\) 就是有至少 \(1\) 个公共质因子,维护这些质因子就行了。把 \(P\) 分解,有 \(10\) 个左右的因子,维护三个东西:正常的区间和,除去这些质因子的区间和,每个质因子的在区间中的出现次数。其实后两个只需要单点查询就行。
CF1393E1/2
设 \(f_{i,j}\) 表示考虑了前 \(i\) 个串,删了 \(j\) 的答案,如果不删就 \(j=L_i+1\)。总级别是 \(\sum L\) 的,时间正确,空间可以滚动数组。
\(f_{i,j}=\sum_{t_{i-1,k} \le t_{i,j}}f_{i-1,k}\)。\(t_i,j\) 表示第 \(i\) 个串删了 \(j\) 的串。
把 \(t\) 按照字典序排序,那么随着 \(j\) 的增加,\(k\) 也增加。可以双指针解决。
这怎么实现呢?用个 vector 按字典序从小到大记下每个串删除字母的编号即可。
考虑二分哈希求 LCP,但是长度是不固定的,同样可以滚动数组压一下,细节有亿点点多。
P9809
像这样带有取模或除法的题,可以考率根号分治。记 \(B=\sqrt V\)。
若 \(x\le B\),直接预处理出答案即可。
否则,假设答案表示为 \(kx+v\),那么 \(k \le B\),枚举这个 \(k\),只需找到最小的 \(\ge kx\) 的数即可。
P9836 种树
\(a_i=p_1^{k_1}p_2^{k_2} \dots p_m^{k_m}\),因数个数为 \(\prod _{i=1}^m (k_i+1)\)。
故答案为 \(\prod_{i=1}^n \prod _{j=1}^{m_i} (k_j+1)\)
考虑一个质因子一个质因子放,那么每次如果放一个新的答案会 \(\times 2\),否则会变为 \(\frac{c+1}{c}=1+\frac{1}{c}\) 倍,显然不如放新的。
所以如果一个存在一个数没有这个质因子,直接把它拉过去是最优的,否则,所有数都有这个质因子,我们应该找 \(c\) 最小的那个。
一个数最多有 \(14\) 个质因子,注意是个,所以对于每个质因子暴力找最优的即可。
ERROR
CF1967A
考虑怎样是最优的。
假如你最后有了 \(b_i\) 张 \(i\) 的卡,考虑按照 \(w,w+1,\dots n,1,2,3,\dots,n ,1,2,3\dots,n,1,2,3,\dots v\) 这么排是最优的,此时答案为 \(n\times\min_{i=1}^n b_i-n+(v+1)+(n-w+1)\)。
这里为什么不把式子合起来,为了更好地贪心。
如 \(b=[6,5,8]\),答案为 \(3\times 5-3+1+2=15\)
最大化 \(\min_{i=1}^n b_i\) 是不劣的,因为你花费 \(n\) 让答案增长了 \(n\)。
那么我们现在要求一个 \(\max\{\min_{i=1}^n b_i\}\),直接二分干掉。
然后你发现我选择减小 \(w\) 和 增大 \(v\) 本质上是一样的,所以暴力算即可。
注意 \(1\le w \le n ,1 \le v \le n\)。
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
ll a[maxn],w;
bool check(ll mid,int n){
ll cnt=0;
for(int i=1;i<=n;i++)
if(a[i]<mid) cnt+=(mid-a[i]);
return cnt<=w;
}
void solve(){
int n;
scanf("%d%lld",&n,&w);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
ll l=1,r=1e18;
while(l<r){
ll mid=l+r>>1;
if(check(mid,n)) l=mid+1;
else r=mid;
}
l--;
for(int i=1;i<=n;i++){
if(a[i]<l) w-=(l-a[i]),a[i]=0;
else a[i]-=l;
}
ll ans=n*(l-1);
int v1=0,v2=n+1;
for(int i=1;i<=n;i++){
if(!a[i]&&!w) break;
if(!a[i]&&w) w--;
if(a[i]) a[i]--;
v1++;
}
ans+=(v1+1);
for(int i=n;i>=1;i--){
if(!a[i]&&!w) break;
if(!a[i]&&w) w--;
if(a[i]) a[i]--;
v2--;
}
ans+=(n-v2+1);
printf("%lld\n",ans);
}
int main(){
int t;
scanf("%d",&t);
while(t--) solve();
return 0;
}
/*
1
5 3
6 6 7 4 6
*/

浙公网安备 33010602011771号