CF专项训练

虽然 CF 在洛谷上已死,但是有好题的话我肯定是要记录一下的啊!!!

Maximum Subsequence

很厉害的一道题,提醒我们看到数据范围非常小无非就是高复杂度的 dp 和搜索,但当dp不利于操作时就考虑搜索,搜索不仅可以考虑记忆化剪枝,还可以考虑双端搜索减少复杂度。

上面就是这题的大体思路,因为我们要用取模操作所以无非用 dp 做,考虑搜索,将数组分为前后两段,分别进行搜索,此时我们想到再对两段进行组合配对不就可以了吗,但是这样的话复杂度完全没降下去。

这时我们考虑贪心,我们要想到有这么一个性质,对于其中一个数组中的数 \(q_i\) 他在 \(p\) 中进行组合时在不超过 \(m\) 的情况下时可以可以找到一个最大的不超过 \(m\)\(p_i\),这比选 所有小于 \(p_i\) 都更优,当我们选择组合超过 \(m\) 时也选择,那用最大 \(q_i +\) 最大不超过也是更优的,所以我们可以排序后双指针或者二分查找即可。

总结:读题后看数据范围推测算法复杂度,搜索多考虑性质剪枝。

Yet Another Minimization Problem

不是很寻常的公式题,这种题只要操作不是很复杂都可以优先拆开。

\[\sum_{i=1}^n \sum_{j=i+1}^n{(x_i+x_j)^2} \]

\[=\sum_{i=1}^n \sum_{j=i+1}^n{x_i^2+2x_ix_j+x_j^2} \]

\[=(n-1)\sum_{i=1}^n{x_i^2}+2\sum_{i=1}^n \sum_{j=i+1}^n{x_ix_j} \]

拆到这我们现放一放,先再看一个式子,我们对他展开。

\[(\sum_{i=1}^n{x_i})^2 \]

\[=x_1^2+x_2^2+\cdots+x_n^2+2x_1x_2+2x_1x_3+\cdots+2x_1x_n+2x_2x_3+\cdots+2x_{n-1}x_n \]

\[=\sum_{i=1}^n{x_i^2}+2\sum_{i=1}^n \sum_{j=i+1}^n{x_ix_j} \]

到这我们发现这两个式子是几乎是等价的,只有前面的平方和不同,现在我们的目的就是为了求平方和和的平方最小,因为前者是个常量不管他,我们需要去求和。

我们如果确定了 \(a\) 序列的总和,那 \(b\) 的总和我们就知道了,看到 \(n\) 很小,和的总值域也很小,所以我们直接背包,设 \(f[i][sum]\) 表示选了前 \(i\) 个数总和为 \(sum\) 的这个 \(sum\) 值时我选了几个数得到的(应该这么形容,大概理解下),然后我们可以对 \(sum\)\(f[i-1][sum-a[i]]+1\) 转移也可以从 \(f[i-1][sum-b[i]]+1\) 转移过来,最后哪个值是由选择n个数得到的对那个 \(sum\) 求值,最后的答案就是:\((n-2)\sum_{i=1}^n{x_i^2}+sum_a^2+(sum-sum_a)^2\)

Penchick and BBQ Buns

感觉构造题就是打表找规律及特殊性质的题,这题要求相同的数距离要是完全平方数。

n是偶数时直接两个两个放就可以1,1,2,2,3,3……

\(n\) 是奇数时我们必须要放奇数个,但我们又不能放 \(1\) 个,那就放 \(3\) 个,这 \(3\) 个每两个之间的距离都得是完全平方数,最边上的两个的距离是中间两个线段的和,即 \(z^2=x^2+y^2\),震惊!!!这不是勾股定理吗,所以说我们构造这个就可以满足了,最小的勾股数是3,4,5 那对应得我们得在 \(x_1,x_{10},x_{26}\) 位置放下 \(3\) 个一样的数,其他位置 \(2\)\(2\) 个放,那就知道了,\(n\) 为奇数且 \(n< 26\),无解,\(n\ge 27\) 如上构造。

Alice's Adventures in Cutting Cake

特性有连续分蛋糕,答案是个区间最大值,我们预处理出来前缀 \(1-i\) 的划分可分给几个人和后缀 \(i-n\) 分人。

然后我们枚举起点,二分查找到可满足的最右边的点,中间的全都是我们可以吃到的,区间求和用前缀和即可。

Robert Hood and Mrs Hood

考虑用差分将区间贡献转化为点贡献,对于一个工作区间 \([l,r]\),因为查询也是一个区间所以将位置 \(l-d+1\)\(1\)\(r+1\)\(1\)

我们再求前缀和就可以得到每个位置的区间 \([i,i+d-1]\) 不同工作数,求最大值最小值的下标即可。

#include <bits/stdc++.h>
#define int long long
#define re register
const int N=1e5+10;
using namespace std;
int n,d,m;
int a[N];
void solve(){
cin>>n>>d>>m;
for(int i=1;i<=m;i++){
int l,r;
cin>>l>>r;
a[max(1ll,l-d+1)]++;
a[r+1]--;
}
for(int i=1;i<=n;i++){
a[i]+=a[i-1];
}
int mx=0,mxid=0,mi=1e9,miid=0;
for(int i=1;i<=n-d+1;i++){
if(a[i]>mx){
mx=a[i];
mxid=i;
}
if(a[i]<mi){
mi=a[i];
miid=i;
}
}
cout<<mxid<<" "<<miid<<"\n";
for(int i=1;i<=n+1;i++){//要多清一个位置
a[i]=0;
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}

明显树形 dp 题,设状态 \(f_{i,0/1}\) 为将当前节点不染/染成白色的最大权值和,那对于不染这个节点可以直接转移 \(f_{i,0}=\sum_{j\in son_i} max{\{ f_{j,0},f_{j,1} \}}\)

否则染这个节点的话,儿子不染色则可以直接转移,儿子染色的需要减去 \(2c\)(儿子节点减 \(c\),当前节点减 \(c\),总权值和减 \(2c\)),转移方程有 \(f_{i,1}=\sum_{j\in son_i} max{\{ f_{j,0},f_{j,1}-2c \}}\)

#include <bits/stdc++.h>
#define int long long
#define ls p<<1
#define rs p<<1|1
#define re register
const int N=2e5+10;
const int mod=998244353;
using namespace std;
int n,c;
int f[N][3];
vector<int> v[N];
void dfs(int x,int fa){
for(int y:v[x]){
if(y==fa){
continue;
}
dfs(y,x);
f[x][0]+=max(f[y][0],f[y][1]);
f[x][1]+=max(f[y][0],f[y][1]-2*c);
}
}
void solve(){
cin>>n>>c;
for(int i=1;i<=n;i++){
cin>>f[i][1];
}
for(int i=1;i<=n-1;i++){
int u,vv;
cin>>u>>vv;
v[u].push_back(vv);
v[vv].push_back(u);
}
dfs(1,0);
cout<<max(f[1][1],f[1][0])<<"\n";
for(int i=1;i<=n;i++){
f[i][0]=f[i][1]=0;
v[i].clear();
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
posted @   sad_lin  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示