杂题选写
Last UPD on 2024/11/12
CF1667C Half Queen Cover
*2400
标签:构造;数学
题目大意
给定一个
注意,皇后
数据范围:
思路
让我们来考虑答案的下界。假设我们放置了
首先,这
此时,我们需要保证这个矩阵的
考虑当
若
CF1906L Palindromic Parentheses
*2500
标签:构造
题目大意
构造一个长度为
数据范围:
思路
让我们来开一下
先让我们考虑一个串 ((((()))))
,我们可以构造出解的下界
再考虑串 ()(((())))
,此时答案变为
若此时我们继续往左边添加 ()
得到 ()()((()))
,此时答案为
但是当我们再添加一个 ()
得到 ()()()(())
,此时答案仍然为
为什么?可以发现,当我们添加一个 ()
后,会多一个 )
来匹配,从而导致答案加 ()
时,匹配的 )
数量就不够了,所以答案仍然为
所以,让我们往右边添加 ()
得到 ()()(())()
,此时答案为
在左边添加 ()
会多一个 )
来匹配,而往右边添加 ()
会多一个 (
来匹配,这两者可以互相匹配,来解决括号不足的情况。
所以,我们可以得到一种构造方式,往两边添加 ()
,且使两边添加的数量尽量平均。
当
CF1917E Construct Matrix
*2500
标签:构造
题目描述
给你一个偶数
- 矩阵中所有数字之和正好为
; - 每一行的异或和相同;
- 每一列的异或和相同。
思路
对于这一道题,当
其次,当
接下来,让我们考虑
然后是
其他位置填上
注意到当
CF1917E Construct Matrix 改
让我们去掉
思路
我们只需要解决
让我们令
首先,因为
先来构造
接着我们按照
接下来我们只需要构造
我们可以在
变成
若我们依次选择第
结束。
Matrix Remake
题目描述
给你三个整数
-
对于所有
都有 。 -
对于所有
都有 的值为奇数。 -
对于所有
都存在一个整数 满足 。
数据范围:
CF1896F Bracket Xoring
标签:构造
*2600
题目描述
给定一个长度为
构造出一种使得
思路
然我们来分析每次操作对于
首先,
其次,每次一定会有偶数个位置被操作,所以若
不妨先假设 ()()...()
来将整个
每次操作,我们可以选择相邻的两个 ()
,这样每个为
但这必须保证每两个
考虑这个该如何构造。
不妨假设现在我们需要让
- 若它们本来就相同,我们直接放
()
。 - 若他们不同,我们可以通过放
((
或者))
来使得它们相同。具体的,我们可以看前面是否有没有被匹配的括号,如果有就放))
,没有就放((
。并且我们可以知道,没被匹配的括号个数一定是偶数。
其中,第
所以,我们至多会使用
CF1227G Not Same
*2600
标签:构造
题目描述
给定大小为
你需要执行至多
思路
有这样一个构造:先将
这为什么是对的?假设在这样的构造下存在第
对于第
CF1491G Switch and Flip
*2800
标签:思维;图论
题目描述
有
- 选择两个整数
,然后交换硬币 ,并将硬币 翻面。
你需要使得第
数据范围:
思路
我们将
我们称一次操作为交换
那么一次操作就会让一个
接下来让我们对于一个大小为
让我们考虑两个环
同样是选择一个反面硬币来进行操作,最后再将两个反面硬币形成的环来一次操作就可以使得这两个环均满足条件。
若环的个数为偶数,我们就可以两两处理。
若环的个数为奇数,那么我们就可以把这个环和前面的一个自环相结合,会多产生一次操作次数。
接下来让我们考虑只有
先考虑当
花费
若是一个
最后会花费
CF702F T-shirts
*2800
标签:数据结构;贪心
题目描述
有
每个人会优先选择能够购买且质量最大的物品购买,若质量一样就选择价格最小的。你需要求出每个人能购买多少物品。询问相互独立。
思路
质量几乎是没用的,我们只需要按照
我们有一个暴力的做法:对于每一个人,顺次枚举每一个物品看能不能选。但这个做法不是很有前途。
让我们考虑另一个暴力:我们来顺次枚举每一个物品,然后看有哪些人能够购买这个物品。
这个问题就相当于:给定一个序列
这看上去很可以用数据结构来维护。考虑平衡树。
对于每一个物品
其中,第一个区间的数不会受到影响,第三个区间的数减去
现在的问题是第二个区间,这个区间内的数减去
实际上,我们可以对第二个区间内的数暴力修改。因为这个区间里的数每次修改至少会减小一半,所以每个数被修改的次数为
AGC016D XOR Replace
*2902
标签:思维;图论
题目描述
现有一个序列,一次操作可以将某个位置变成整个序列的异或和。问最少几步到达目标序列。
思路
神仙建图。
先让我们来考虑每次操作相当于什么。假设当前
然后我们可以按照以下方式来建边:若
若我们走了一条边
但是很可能不存在这样一条边,此时可能会存在一条
可以发现,第一个操作会使边数减少一,而第二个操作后边数不变。
而我们最终的目标就是删除所有的边。所以,我们要最小化操作二的数量。
令第
而对于不存在
所以,答案就是边数加上连通块数量减一,但是若
CF1713F Lost Array
*2900
标签:构造;数学
题目描述
给出一个从
- 对于
, 。 - 对于
, 。 - 对于
, 。
现在,给出
思路
让我们考虑如何用
我们先将
我们发现,当
同理,我们也可以求出对角线对
而因为这是异或运算,所以子集和的逆即为子集和,超集和的逆即为超集和。
CF2021E Digital Village
*2300/2500/2800
标签:动态规划;dp 优化;闵可夫斯基求和;Kruskal 重构树;贪心;长链剖分
题目描述
给定一张有
定义一个关键点的权值为该路径上边权的最大值。最小化所有关键点的权值和。你需要对于每一个
数据范围:
- E1:
。 - E2:
。 - E3:
。
思路
让我们把该图的 Kruskal 重构树先建出来。此时所有原图中的点都变为叶子节点,边权转移到了点上。
令
其中,
初值有
然后我们就可以在
容易发现,对于一个
实现时,直接插入这次多出来的那一段即可。
时间复杂度
PS:还有一种做法是转化问题后贪心,然后用左偏树维护,类似于 BZOJ3252 攻略。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll inf = 1e16;
int n, m, p, id[200005];
bool flg[200005];
int fa[200005], siz[200005], sizp[200005];
ll sum[200005];
priority_queue<ll, vector<ll>, greater<ll> > q[200005];
void merge(int u, int v) {
if(q[id[u]].size() < q[id[v]].size()) swap(u, v);
while(!q[id[v]].empty()) q[id[u]].push(q[id[v]].top()), q[id[v]].pop();
id[v] = id[u];
}
int FindSet(int x) {return fa[x] == x ? x : fa[x] = FindSet(fa[x]);}
struct edge {
int u, v, w;
bool operator <(const edge &t) const {return w < t.w;}
} arr[200005];
void solve() {
scanf("%d %d %d", &n, &m, &p);
for(int i = 1; i <= n; i++) {
flg[i] = false;
while(!q[i].empty()) q[i].pop();
}
for(int i = 1, x; i <= p; i++) scanf("%d", &x), flg[x] = true;
for(int i = 1; i <= m; i++) scanf("%d %d %d", &arr[i].u, &arr[i].v, &arr[i].w);
sort(arr + 1, arr + m + 1);
for(int i = 1; i <= n; i++) fa[i] = i, siz[i] = 1, sizp[i] = flg[i], q[id[i] = i].push(0), sum[i] = 0;
for(int i = 1; i <= m; i++) {
int u = FindSet(arr[i].u), v = FindSet(arr[i].v);
if(u == v) continue;
fa[u] = v;
ll tmpl = q[id[u]].top(), resl = 1ll * sizp[u] * arr[i].w - sum[u]; q[id[u]].pop(), q[id[u]].push(tmpl - resl); sum[u] += resl;
ll tmpr = q[id[v]].top(), resr = 1ll * sizp[v] * arr[i].w - sum[v]; q[id[v]].pop(), q[id[v]].push(tmpr - resr); sum[v] += resr;
merge(u, v);
siz[v] += siz[u], sizp[v] += sizp[u], sum[v] += sum[u];
}
int rot = FindSet(1);
ll ans = 0;
for(int i = 1; i <= n; i++) {
ans += q[id[rot]].top();
printf("%lld ", sum[rot] + ans);
q[id[rot]].pop();
}
puts("");
}
int main() {
int t; cin>>t;
while(t--) solve();
return 0;
}
CF2003F Turtle and Three Sequences
*2800
标签:状态压缩;动态规划;随机化(color-coding);dp 优化
题目描述
有三个序列
需要选择长度为
;- 所有索引
的所有 都是两两不同,即不存在两个不同的索引 , 使得 。
找出
思路
https://www.cnblogs.com/ddxrS/p/18430320
CF208E Blood Cousins 改 / Cnoi2019 雪松果树
标签:dfs;差分
题目描述
有两种询问:
- 求出一个节点
的 级祖先。 - 求出一个节点
的 级子孙数量。
你需要在时空均为
思路
我们可以离线来处理所有询问。
先考虑第一个问题:求
求出一个节点的
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, q, fa[N], cnt[N], ans[N];
vector<int> E[N];
vector<pair<int, int> > que[N], in[N];
void dfs1(int x, int dep) {
fa[dep] = x; for(auto p : in[x]) if(dep >= p.first) que[fa[dep - p.first]].push_back(make_pair(dep, p.second)); else ans[p.second] = 1;
for(auto y : E[x]) dfs1(y, dep + 1);
}
void dfs2(int x, int dep) {
for(auto p : que[x]) ans[p.second] -= cnt[p.first];
cnt[dep]++; for(auto y : E[x]) dfs2(y, dep + 1);
for(auto p : que[x]) ans[p.second] += cnt[p.first];
}
int main() {
scanf("%d %d", &n, &q);
for(int i = 2, x; i <= n; i++) scanf("%d", &x), E[x].push_back(i);
for(int i = 1, a, b; i <= q; i++) scanf("%d %d", &a, &b), in[a].push_back(make_pair(b, i));
dfs1(1, 0), dfs2(1, 0);
for(int i = 1; i <= q; i++) printf("%d ", ans[i] - 1);
return 0;
}
CF2021D Boss, Thirsty
*2500
tag:动态规划
题目描述
给定一个
对于矩阵的第
- 对于
,均有区间 和 相交; - 对于
,均满足区间 不包含 。
最大化你选出的利润和。
思路
https://www.cnblogs.com/ddxrS/p/18457534
CF1707E Replace
*3500
tag:倍增,思维
题目描述
给定一个长为
定义一个二元组函数如下:
你需要回答 -1
。
思路
模拟赛 T4,然后发现之前做过。
令将区间
可以考虑倍增,即只求出
但是这样做我们就需要提前预处理出
但是这里有一个性质:若区间
不难用归纳法证出。
由此性质,我们只需要预处理出
具体可以使用 rmq + 倍增来维护。
CF1771F Hossam and Range Minimum Query
*2500
tag:主席树,随机化
题目描述
给定一个序列
思路
先考虑出现次数为奇数这个限制条件,发现我们可以使用异或来维护,若存在一个值域区间
所以,我们只需要先将所有数随机赋权,然后用主席树维护异或和,每次询问在主席树上二分即可。
CF1746F Kazaee
*2800
tag:数据结构,随机化
题目描述
支持两种操作:
- 将
设为 。 - 询问
中是否所有数的出现次数都为 的倍数。
思路
考虑随机赋权,然后求出区间和
但这样正确率是不够的,当
所以我们可以多随机几次,大概
CF1136E Nastya Hasn't Written a Legend
*2200
tag:数据机构,线段树
题面描述
给定长为
+ i x
,表示 ,然后重复以下过程:若 ,则 ,否则结束本次操作。s l r
,输出 。
思路
先让我们来考察
令
也就是说,我们只需要二分找到连续段的最后一个
我们只需要用线段树维护
查询时直接查询区间和,再加上
CF2025F Choose Your Queries
*2700
tag:思维
题目描述
初始有
你需要保证任意时刻每个变量的值都不小于
最小化
思路
将每次操作看成一条无向边,每次操作我们相当于给边定向,每次将入的那个点进行操作,可以发现,若一个点的入度为奇数,那么这个点最后的值为
所有我们的目标就是最小化入度为奇数的点的数量。
对于每一个连通块单独考虑。问题的下界是连通块中所有节点的度数和
我们先把这个连通块的 dfs 树跑出来,对于非树边,我们先贪心的将所有指向父亲节点。
之后从叶子开始考虑每个点,若当前这个点的入度为奇数,就将这条树边指向自己,否则指向父亲。显然,最后只会有根节点的入度可能为奇数。
CF1929F Sasha and the Wedding Binary Search Tree
*2300
tag:组合数学,树形结构
题目描述
给定一棵二叉搜索树,其中一些节点已经点权,询问有多少种在剩余节点设置点权(值域
数据范围
思路
对于一棵二叉搜索树,我们将它中序遍历的序列跑出来,得到的点权序列一定是不递减的。
依次考虑每一个连续的 -1 的段
由于
CF848C Goodbye Souvenir
*2600
tag:数据结构,树套树,分块,莫队,cdq 分治
题目描述
给定一个长度为
支持两种操作,单点修改,区间查询所有颜色的权值和。
数据范围
思路
直接计算每种颜色的贡献不太好算,让我们把贡献拆开:记
由于我们需要同时保证
在线可以用分块/树套树来维护。
离线可以用莫队/ cdq 来维护。
CF364D Ghd
*2900
tag:随机化,暴力枚举
题目描述
给定一个大小为
思路
若我们确定了一个数
通过枚举
这肯定不能接受。但是题目满足至少有
所以,我们只需要随机选取
CF1334F Strange Function
*2500
tag:动态规划 dp,数据结构
题目描述
定义函数
给出两个序列
数据范围:
思路
将问题转化为保留一些元素,使得保留的元素代价和最大。
考虑 dp,定义
分以下三种情况来讨论:
-
,此时选择 ,必然会使 中存在 ,而 和 有不匹配,所以 不能选。 -
,此时可以选择 ,并决定 是否匹配 ,所以有转移 。 -
,此时无论是否选择 , 中都不可能存在 ,所以有 。
直接转移是
之后可以用数据结构维护后缀加,单点最大值,来优化到
CF1773I Interactive Factorial Guessing
*2500
tag: 暴力枚举,交互题
题目描述
你需要找到一个数
思路
通过一个位置的值,我们可以将这些数分成至多
同时
注意一些实现上的细节:第一次询问的位置是固定的;只需要询问前
CF351C Jeff and Brackets
*2500
tag:动态规划,矩阵快速幂优化 dp
题目描述
构造一个长度为
数据范围:
思路
先考虑一个朴素的 dp:定义
有转移:
直接转移是
相当于有
实际上,
可以用矩阵快速幂来维护转移。
时间复杂度
CF351C Jeff and Brackets 改
数据范围改为:
需要一种
CF1380F Strange Addition
*2600
tag:矩阵,数据结构,动态 dp / ddp
题目描述
对于非负整数
- 将
一上一下写在两行,并按照低位对齐。 - 将它们的每一位加起来,并将每一位的结果从高位到低位连接在一起,得到的就是
。
(你可以认为,两个数都有无穷多的前导 0)
你现在有一个仅包含
x d
- 将 的第 个数码替换成数码 。
(注意,
每次操作过后,你需要输出,有多少个有序对
思路
进位只会在前一位是
可以写出一个 dp,令
有转移:
然后有
将转移写成矩阵形式:
直接用线段树维护。
初值
注意修改时要修改
时间复杂度
CF1957F Frequency Mismatch
*2600/2700
tag:随机赋权,主席树,二分
题目描述
给定有
有
思路
考虑随机赋权。
那么对于一个值域区间若此区间内所有颜色的和不同,那么就存在一种颜色满足条件。
可以用主席树储存信息,每次二分来找满足条件的颜色,找到
CF138D World of Darkraft
*2500
tag:博弈论,动态规划 dp
题目描述
有一个
- 若该格子上的字母为 L,则将直到该格子左下或右上的第一个黑色格子(或边界)的格子全部涂黑。
- 为 R,方向为左上或右下。
- 为 X,相当于同时有 L 和 R。
最后无法选择格子的人输,判断先手是否有必胜策略。
思路
将棋盘转 45 度,将
每次选择相当于横着或竖着将这个联通块切成两部分。
可以用四个字母
连通块内的切割不会影响到其它连通块。
所以我们每次切完后可以将两个连通块分开考虑。
用 sg 函数来计算答案。
枚举当前连通块内的每一个方格
- 若该方格为 L,那么有
的贡献。 - 其它两种情况同理。
可以将原图黑白染色,然后单独考虑黑点和白点,他们是不影响的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现