国庆集训——10.5
CF1012D
总数最多减2
减1的情况
1.abab....(一长串)
a/b(一个)
2.ab
ab
贪心:尽量让两个串长度(交替数)相等/差不多(尽量多减2)
CF360E
s1 -> f < s2 -> f
1.Q:修改要么修改到左端点,要么右端点?
A:一条路要么都不在或都在(怎样无影响),要么在s1或s2(最短或最长)
2.正解
先把所有都修改成Ri,接着对每条可修改边(x->y)跑最短路
d1[x] < d2[x] 则将此边修改成Li
证明: 1.(x,y)在1和2最短路上
2.在1路上,尽量改小
3.在2路上,已经满足
4.都不在,改小后也只会是上三种情况的一种
二分
二分查找
1.whlie(L < R) {
if(chk(mid/mid+1)) L = mid+1;
else R = mid;
}
[ ]
[L mid][mid+1 R]
2.while(L <= R) {
if(chk(mid)) L = mid+1,ans = mid;
else R = mid-1;
}
[ ]
[ mid-1][mid][mid+1 ]
在单调递增中找<=x的最大值
while(L < R) {
int mid = (L+R)>>1;
if(a[mid+1] <= x) L = mid+1;
else R = mid;
}
while(L <= R) {
int mid = (L+R)>>1;
if(a[mid] <= x) L = mid+1,ans = a[mid];
else R = mid-1;
}
实数二分
[L,R)
[L,mid) [mid,R)
NOIP2012 二分+差分
CF562 Div2 C
注:单调不减(a[i] <= a[i+1])
二分操作次数?
chk(mid)
贪心策略:到i,[1,i]单调不减并让a[i]最小
具体维护:
1.cur > lst,看能不能加回lst
2.cur == lst,直接取lst
2.cur < lst,看能不能加到lst
CF985D
二分底边长,算等腰三角形(或等腰梯形,分奇偶讨论一下)面积,个数 >= n
则合法
第K大区间
N <= 1e5
*二分常见套路
1.最大值最小/最小值最大
2.最大/最小
3.第k大/小
二分mid,看多少区间的值 >= mid
实现:
1.对于每个L,找到最近的R,使得[L,R]的值 >= mid,则贡献(n-R+1)个区间
2.找最近的R:尺取法(双指针法(two pointers))
L = 1,R = 0,让R变大,不能移则移L
O(n)
3.支持增加,减少,查询区间值
cnt 统计多少 >= mid
cnt > 0 则行
IOI2013 Robert(玩具)
最小化时间
二分时间?
每个机器人可用最多mid次
nlog^2n
NOIP2018 赛道修建
二分+贪心+(STL multiset)
倍增
倍增思想的最基本最通用模型:一个图,每个点只有出边
1.询问每个点(u)走k步能走到哪
2.假如有边权,询问边权和,积,最大值,最小值,gcd.....
要求单次操作时间复杂度为O(logn)
nxt[u][logk]
nxt[u][0] = v;
for(int i = 1;i < ; ++i) {
//for(int u = 1;u <= n; ++u)
nxt[u][i] = nxt[nxt[u][i-1]][i-1];
}
询问
将k二进制拆分(logk)
维护信息
info[nxt[u,i]] = merge(info[u,i-1],info[nxt[u,i-1],i-1]);
倍增求快速幂
经典模型:ST表,LCA
JSOI2015 最大公约数
solution:
预处理出gcd倍增数组f[i,j]
然后呢......
结论(性质):gcd(aL -> aR) 变化次数 <= log(R-L)
对于gcd相同的段,倍增往后跳
[ 1, 2, 3, 4, 5, 6,7,......]
[15,15,15,15,15,15,5,5,5,5..]
判断是否有gcd的因子即可
1 -> 6
排列问题
原排列 nxt[i,j]
r[i] i的最近
ans[i] >= i 的最近
判断ans[Li] 是否 <= Ri
CF97E
建dfs树,树上差分...
开车旅行
区间覆盖问题
1.nxt[i] 表示从坐标i开始的左端点>i的最近的区间的右端点
倍增优化跳的过程
nxt[i,j]
维护nxt[i,0]:从右往左扫,记录minr,
2.nxt[i] 表示从坐标i开始的左端点<i的最远的区间的右端点
倍增优化跳的过程
nxt[i,j]
数据结构
二叉堆
实现:STL
tips:前k大,最大/最小
priority_queue实现方便的删除
建一个删除堆,查询的时候判断一下堆顶是否在删除堆,如果在则把两个都
出堆
中位数
1.vector乱搞
2.对顶堆
大根堆(seil(n/2)) 小根堆(floor(n/2))
序列合并
将a[1]+b[1]入堆,每次取堆顶a[i]+b[j]后加入min(a[i+1]+b[j],a[i]+b
[j+1])(未入过堆)
3.平衡树
镇静剂
维护si
从右往左做
1.前K大,第k大
控制左端点
[ ] ]
L R1 R2
(L,R1,R2)三元组
R3 = (L,R1,R2)
[ ] ] ]
L R3
(L,R1,R3)
(L,R3,R2)
S = s[R]-s[L-1]
s[L-1]固定,最大化S -> 取最大的s[R],并记录位置
冰茶姬