2021-05 杂题泛做
Codeforces 1043G
不难证明出现的答案答案是不大于 的,否则是 ,构造形如:
直接分开讨论四种答案对应的若干情况
-
的是
-
写一个优秀的拆分, 是查
考虑这样一个结论:子串存在的长度 的 一定满足 和 的后缀数组上的排名不超过
证明考虑如果有超过 个后缀满足在这两个中间,那么其和两端的 都大于 ,明显不存在
-
这个部分直接判是不是两端的字符出现了两次即可
写出来优秀的拆分之后维护 表示从当前点开始最小的位置满足该子串是一个 串,是一个
四合一挺难受的
平面最近点对
记录本题分治做法
考虑和建立 的做法类似的,对于当前分治区间 ,取 这维的中位数,递归左右部分,求得两个子集的
考虑合并两边的信息不难发现只有 中的点有用
将区间里面的点按照 轴归并之后将这些点取出,写一个带朴素剪枝的暴力即可
考虑这个暴力的正确性:
对于一个点,可能更新答案的点必然在不大于 的一个矩形里面
将其分割成 的几个小部分,那么每个矩形框里必然不能有超过 个点,小矩形对角线的长度为 ,那么复杂度正确,而且常数不大
Luogu3322
关注到是一个深度为 的线段树的形式,那么这个操作的先后顺序和是不是能翻成一个标准序列无关
所记录的东西就是操作的次数,并从小向大 ,最后 ans+=fac[num];
那么找到所有不是 递增的段,如果超过两个一定不合法,剩下的枚举所有情况交换递归
注意在不合法状态有 个的情况下,如果得到左 的解可以不枚举右 ,通过这样的剪枝得到的复杂度为
联通欧拉图计数
定义是能经过每个边恰好一次并回到出发点的图
设 表示有 个点的欧拉图的数量(不保证联通),因为图的性质(每个点度数都是偶数),那么结果是
设联通欧拉图的数量为 ,枚举 号点所在的联通块的大小
想要分治 的话好像也不是不行,拆开组合数做即可
Codeforces986E
差分询问,运用质数个数少,次数小等和 本质是次数取 等性质 处理即可
Codeforces809E
首先得到这样一个东西:
证明直接拿质因子拆就行了,式子变成:
显然枚举 接着把 扔到其所有因子的 里面,设如下两个函数(没想到吧,竟然是标准的莫比乌斯反演式!)
那么把 拆开,对每个质因子整个虚树就能得到
因为要求 次 ,那么建议使用倍增
本来还想拆 的,同时学会了简单证明了这个式子
Codeforces639F
不难发现题目中要求的就是一个边双,那么先把原图按照边双整成一个森林
对于每个询问,把边和点的所有集合全拉出来建虚树森林,在上面照样跑边双就行了
如何写边双?
inline void tarjan(int x,int pre){
dfn[x]=low[x]=++tim;
for(reg int i=head[x];i;i=e[i].nxt){
int t=e[i].to; if(!dfn[t]){
tarjan(t,i); low[x]=min(low[x],low[t]);
if(low[t]>dfn[x]) bridge[i]=bridge[i^1]=1;
}else if(i!=(pre^1)) low[x]=min(low[x],dfn[t]);
} return ;
}
点双直接判是不是 然后弹栈,记割点如下
if(x!=rt||cvcc>1) cut[x]=1
其中 指 开始的地方
Codeforces925E
有一些显然的思考是把每个点的点权先整成 ,有变成白点的操作就给链加
先树剖,然后对树分块,每次修改暴力跳重链按题意模拟即可
Codeforces896C
使用珂朵莉树,其本质是使用了数据随机的情况下会有 的概率是区间覆盖操作
大体就是维护一个里面表示区间的 ,每个区间的值是相同的
核心函数就是 assign(),split()
,分别表示将区间覆盖和拆开区间,剩下全是直接暴力
实现上有些新的语法:
-
mutable:
能避开 里面的 限制 -
erase(iterator_L,iterator_R):
删掉 里面 的迭代器
BZOJ3786
用欧拉序( 各在序列里面加入一次 )来维护子树
外层不论套 抑或是 都可以直接对着序列来交换子树
但是最大的局限性一是维护森林将十分复杂,二是不能换根
本题树上维护 即可,再附 的写法
inline int merge(int x,int y){
if(!x||!y) return x+y;
push_down(x);
push_down(y);
if(rand()%(sz[x]+sz[y])<sz[x]){
rs[x]=merge(rs[x],y);
push_up(x);
return x;
}else{
ls[y]=merge(x,ls[y]);
push_up(y);
return y;
}
}
inline void split(int rt,int siz,int &x,int &y){
if(!rt) return x=y=0,void();
if(sz[rt]==siz) return x=rt,y=0,void();
if(!sz[rt]) return x=0,y=rt,void();
push_down(rt);
if(sz[ls[rt]]>=siz){
split(ls[rt],siz,x,ls[rt]);
y=rt,fa[x]=0;
}else{
split(rs[rt],siz-sz[ls[rt]]-1,rs[rt],y);
x=rt,fa[y]=0;
}return push_up(rt);
}
Codeforces878C
不难发现如果两个选手不是所有维度大小性相同,那么都有可能获胜
所以对于这样的选手缩一把点,维护一个点的个数
考虑到 的判等方式是两者的 都不成立,那么使用 维护一个集合里面的维度最值和集合的大小即可
答案也就是 “最大” 的集合的大小
Luogu4426
考虑树上独立集的求法,暴力 可以获得 的好成绩
直接套到图上面不太可取,其实冲突的地方只有非树边 条
-
我会二进制枚举!
分 次方枚举每条边是上侧点选还是下侧点选,剩下的还是一个朴素
值得注意的是可以能有 的下侧点是 的上侧点,所以标记的时候要稍微复杂一点
-
:有很多的 是没有用的,同时如果不在任意一对非树边涉及的点的路径上的点的 永远不变
建立这 个点的虚树,别的状态的 值可以提前预处理出来,剩下的 照样二进制枚举做即可
时间复杂度
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律