前言
因为要保证能力的提升,不能啥题都是写写。
所以开一个口胡题解坑。
可能以后有心情和能力也会来写一写收录的题。
至少留下一个思考过的痕迹。
实在太水可能就不口胡啦。
有些题也会写写。
2017.3.13
bzoj3679
计算可以被分解成1~9的乘积且在1e9内的数只有5194个
然后可以数位dp
bzoj3756
直接给Trie建SAM是伪的。
这个伪指的是深搜建。
允许离线用宽搜建不是伪的。
建出来就好做了。
2017.3.14
bzoj3069
没有强在我倒过来做
然后每次加一条边,如果连接两点联通了,肯定树路径上的点就飞了。
反正LCT维护发。
bzoj3070
指数在log以内
固定指数的话,指数有单调性。
用个堆维护,取k次大概。
2017.3.15
bzoj3073
想到了线段树优化连边。
但是只想了一颗线段树是log^2的。
膜拜了题解,就建两颗线段树,然后一条边再来建中间节点。
这样就是一个log。
最后这题打算写写。
bzoj3494
这个。。
难道不是只需要保留生成树就行了吗……
(显然我是错的?
2017.3.16
bzoj3492
妙啊。
大概就是结论+DP。
这题口胡完后写了,可以看我博客题解。
bzoj3495
每个城市只有是否是首都两种状态。
对于每个国家可以建立前缀和和后缀和节点,同样只有是0还是1两种状态。
然后跑2-sat。
想练2-sat的时候也可以来写写这题。
2017.3.17
bzoj4774
裸斯坦纳树
2017.3.18
JZOJ做的一道题
题意说是求最大匹配数为m的n个节点无根树方案数。
设f(n,m,a,b)来表示一颗有根树,状态为(n,m),它的最右子树状态(x,y)<=(a,b),这样的有根树的方案数。
可以看到,我们用了一个二元状态表示一颗有根树。
(x,y)表示x个节点,有y/2个最大匹配,y是奇数表示根节点一定在最大匹配中,否则表示根节点不必需在最大匹配中。
定义(x,y)<(a,b)为
x<a
x
<
a
或x=a且
y<b
y
<
b
一个有根树,我们将它的儿子根据这样的二元状态排序。
如果二元状态一样的两个儿子,根据其是该状态下的第几种方案排序。
这个dp我们倾向使用记忆化搜索实现。
转移的话,找到小于(a,b)的最大状态(p,q),从(p,q)转移过来。
或者最右儿子状态就是(a,b),我们枚举有几个,然后用组合数计算。
怎么用组合数计算?
考虑解决这样一个问题,求多少长度为y的序列a,满足ai<=ai+1,且1<=ai<=x。
可以看做把y分成x份,每份至少为0,一份的数字表示的是该种数字的序列中的出现次数。每个数字的出现次数确定了那么序列唯一。
这样根据经典隔板法是
Cx−1x+y−1
C
x
+
y
−
1
x
−
1
这个dp有啥用呢?注意无根树计数其实就是选一个重心然后转化为的有根树计数!所以只要第一层限制最右子树节点个数小于等于n/2即可。
不过我们还要去重。
为什么?因为偶数节点的树可能有两个重心!
考虑减掉这种情况,枚举两颗n/2大小的树的状态类似算一算即可。
2017.3.19
noip2016T2的加强版,多了修改w和加边删边。
因为显然啥数据结构都不能做这种玩意了,所以就想想怎么大暴力。
大暴力当然就是分块啦。
但这里说的不是树分块,而是对操作分块,也就是定期重构!
每S个操作后我们就重构一遍,现在只需考虑这S个操作内。
对于加边删边的操作,对这S个操作中不会影响的边进行保留,其余删去,然后根据联通块缩点,便得到了S个联通块。
每次对于一条打卡路径,可以暴力搜出经过哪些联通块,对于每个联通块我们找出对应路径。
那么只要分别在这S个联通块内都使用一侧noip正解就好了。
考虑修改W,对于每次一条打卡路径,都去枚举每一个修改W操作,看看这个操作是否会带来影响(未修改前没观察到而修改后观察到了,未修改前观察到了而修改后没观察到)。判断一个点是否被观察到,要先判断是否在打卡路径上,可以用时间戳完成子树包含判断来完成链包含判断。
这样做复杂度是多少呢?
我们做
ms
m
s
次
每次的s个打卡,被拆分到s个联通块中,需要s^2的时间,我们还要扫一遍树来保留未被影响的边,需要n的时间。加边和删边让我们复杂度为
ms∗(n+s2)
m
s
∗
(
n
+
s
2
)
那么修改W呢?s个修改W,我们枚举了s个打卡,所以也是
ms∗s2
m
s
∗
s
2
这种情况s取根号时坠吼的,当然也可以玄学取值。
noip那题怎么做就不用说了吧T_T。
bzoj4293
根据长高速度排序。
那相对顺序永远一样。
我们只是要考虑怎么维护,线段树啦,标记就是上一次收割砍到多少,啥时候割的。
2017.3.20
luoguP3676
链剖+讨论可做,但是两个log
我们思考如果是和,显然根是p答案就是
∑dis(i,p)∗vi
∑
d
i
s
(
i
,
p
)
∗
v
i
这个可以建立点剖树来维护询问和修改。
现在是平方和?其实差不多。
∑v2=(∑v)2−∑∑v1v2
∑
v
2
=
(
∑
v
)
2
−
∑
∑
v
1
v
2
所以其实要维护的差不多,因为你可以看做你要维护
∑dis(i,p)∗vi
∑
d
i
s
(
i
,
p
)
∗
v
i
∑dis(i,p)∗vi2
∑
d
i
s
(
i
,
p
)
∗
v
i
2
设和为sum,还要维护
∑dis(i,p)∗sum
∑
d
i
s
(
i
,
p
)
∗
s
u
m
luoguP3672
设f[i,j]表示一个i的排列逆序对个数为j的个数
每次加入i+1,后面有多少个数就增加多少逆序对。
不难写出转移
f[i,j]=∑f[i−1,j−k]
f
[
i
,
j
]
=
∑
f
[
i
−
1
,
j
−
k
]
最后可以从大的往小的推,来逐位确定。
bzoj3529
设
S(i)=∑d|id
S
(
i
)
=
∑
d
|
i
d
S可以在n log n的时间内求出。
我们要求
∑ni=1∑mj=1S((i,j))∗[S((i,j))<=a]
∑
i
=
1
n
∑
j
=
1
m
S
(
(
i
,
j
)
)
∗
[
S
(
(
i
,
j
)
)
<=
a
]
∑md=1S(d)∗[S(d)<=a]∗f(d)
∑
d
=
1
m
S
(
d
)
∗
[
S
(
d
)
<=
a
]
∗
f
(
d
)
其中
f(d)=∑ni=1summj=1[(i,j)=d]
f
(
d
)
=
∑
i
=
1
n
s
u
m
j
=
1
m
[
(
i
,
j
)
=
d
]
我们显然可以反演一波
∑md=1S(d)∗[S(d)<=a]∗∑m/di=1μ(i)∗n/(d∗i)∗m/(d∗i)
∑
d
=
1
m
S
(
d
)
∗
[
S
(
d
)
<=
a
]
∗
∑
i
=
1
m
/
d
μ
(
i
)
∗
n
/
(
d
∗
i
)
∗
m
/
(
d
∗
i
)
设T=d*i,交换主体
∑mT=1n/T∗m/T∗∑d|Tμ(T/d)∗S(d)∗[S(d)<=a]
∑
T
=
1
m
n
/
T
∗
m
/
T
∗
∑
d
|
T
μ
(
T
/
d
)
∗
S
(
d
)
∗
[
S
(
d
)
<=
a
]
设后面是a(T)
我们按照a值离线处理询问,每次更新一下a即可。
然后这个我们用线段树来维护S的区间和。
CC sumdis
这题好妙,但是不想打。。
我们分治,处理跨中线的最短路统计,其余递归处理。
显然删除中线那的三个点会使整个图不连通,也就是必须经过这三个点!
那么对左右的点用递推求出到三个点分别的最短路。
现在对于左右两个点,就是从三个中选一个,那么我们如何快速统计呢?
比如我们认为会经过的是第一个点,左边点到三点距离分别为a,b,c,右边点到三点距离分别为x,y,z。
那么有a+x<=b+y,a+x<=c+z
移项得a-b<=y-x,a-c<=z-x
这就是二维偏序的问题,直接大力上树套树是两个log。
然后一维可以用指针扫,第二维用线段树就可以啦!
2017.3.23
ReverseMancala
有n个箱子,按环状摆放,标号为0..n-1,箱子 i 有 a[i] 个球
你每次可以进行以下两种操作中的一种:
选择一个箱子x,拿出他的所有球,往顺时针走,每走一步放下一个球,直到放完为止
选择一个箱子x,每次从当前箱子拿出一个球,然后往逆时针走一步,直到遇到一个空箱子,把拿出的球都放下
给出初始状态和目标状态,构造一种方案
N<=10, a[i]<=10
第一种操作的逆操作其实就是第二种操作!
于是局面可逆。
把局面A变成局面B。
找到一个局面C作为中转站,局面C只有一个箱子里有球。
A使用第一种操作到达C,B使用第二种操作到达C。
Random Walk
有一个无限大的二维平面,一开始你在(0,0)上,你会走N步,每次在上下左右四个方向里随机选择一个后往那个方向上走一步。
求期望经过多少格子,答案对998244353取模
N<=5000
有个地方还没明白,什么时候懂了来补。
Dictionary
n个长度不超过10的字符串,只包含小写字母和问号,问你有多少种给问号填小写字母的方案,使得字典序有
s[i]<s[i+1]
s
[
i
]
<
s
[
i
+
1
]
设f(i,l,r,j)表示只看从第i个位置起,区间[l,r]的字符串,s[r]的第i位必须不超过j,那么给位置的问号填字母有多少方案数满足
s[i]<s[i+1]
s
[
i
]
<
s
[
i
+
1
]
转移的话我们可以枚举末尾哪一段开头等于j,当然也可以没有等于j的,然后就n^3*|S|*26做完啦!
2017.3.24
bzoj1135
首先我们要会hall定理。
然后我们可以轻松证明只需要考虑连续一段。
然后假设i号有ai个人。
∑rlai<=(r−l+1+d)∗k
∑
l
r
a
i
<=
(
r
−
l
+
1
+
d
)
∗
k
这是具备完美匹配的条件,太丑了,不如给每个ai减去一个k!
∑rlai<=d∗k
∑
l
r
a
i
<=
d
∗
k
多美啊!右边居然是常数,那么我们只需要用线段树动态维护最大子段和即可。
bzoj3698
其实本来在to do list中的突然就不想写了2333
建图非常显然,对每行每列都建一个点,这是个二分图。
比如行摆左边,列摆右边,源汇连的边上下界分别是对应数上下取整的结果,费用设为1(只有源连出的费用设为1)。
第i行向第j列连的边上下界也是a[i,j]上下取整的结果,费用设为0。
先判定有没有可行流,再跑最小费用可行流。
或者不加费用,判定可行流后也可以做最大流。
bzoj3509
循环展开太强了
显然可以设出一个生成函数
∑ai∗xi
∑
a
i
∗
x
i
表示大小为i的数有多少个。
a[j]-a[i]=a[k]-a[j]就等价于2*a[j]=a[i]+a[k]
枚举j,弄出两边生成函数,可以FFT计算卷积。
这样特别暴力T_T
考虑分块,同样是枚举j。
如果i与k任意一个和j处于同一块,显然特别好做!
否则,我们可以算出两端块的生成函数卷积。
这样只有根号次FFT。
于是写了这题被卡常233
2017.3.29
bzoj4426
我们把人分成两种,包含别人的人和不包含别人的人。
对于不包含别人的人,按右端排序后左端也有序,可以做决策单调性dp。
对于包含别人的人,如果和自己包含的人所处一个组则无贡献。为了最优化答案肯定是选出长度最大的一些单独成组,其余和自己包含的人同组。
bzoj1966
每次n^2检验即可
bzoj4429
把每条式子对应值弄出来做二分图匹配。
bzoj4292
日常想复杂T_T
f(n)<=18*9^2
枚举t=f(n),那么n就确定了,因为n=k*f(n)
然后检验f(n)是否为t即可
bzoj4771
果然我这种辣鸡不会做
考虑没有深度限制的话,只要对于同一种颜色,按dfs序排序,每个位置+1,相邻lca处-1。
那么子树询问就是区间求和!
现在有深度限制,按深度从小到大插入即可,每个颜色用个set维护dfs序。
应该会写一下。
2017.3.30
口胡:
sam大爷问,有多少颗有根带标号的树,满足根节点是1,根是第1层,奇数层节点一共有k个,树的大小是n。
发现其实就是左边k个点右边n-k个点的完全二分图最小生成树计数。
不过带标号还要乘组合数,而且它还钦点了1在X集合。
然后就和文艺计算姬那题差不多啦!
命运的构造(一道题的名字):
Samjia最近被下发了出题任务。
于是他整日沉吟在出题的苦恼中。
他想起一段话:
“我单不知,像鸟儿那样飞在不高的空中俯看那片密如罗网的胡同,会是怎样的景象?飞在空中而且不惊动下面的人类,看一条条胡同的延伸、连接、枝枝叉叉地漫展以及曲曲弯弯地隐没,是否就可以看见了命运的构造?” —-《故乡的胡同》史铁生
他很好奇,自己命运的构造是怎样的,于是他向哲学家看了看自己的命运会如何,哲学家给了他一副很大的有向无环图,命运如流,每个人都不明白推动自己前行的到底是什么,理智么,情感么,憎恨么,贪婪么?
命运是不断变化的,就算这是大概的方向,但在每一个重要的点上都有重大的变故,具体来说,每个点有x一个点权a[x](初始所有a[x]=0),这个a[x]会在某个时间点变动,由于这样的影响是从这个点一直到所有可到达的结尾的,所以一个a[x]的变动会引起后面许多点的a[x]的变动
有两种可能的变动:
“1 u x”:对于所有点u可以到达的点v,a[v]变成x
“2 u x”:对于所有点u可以到达的点v,a[v]更新为min(a[v],x)
当然还有询问,每次的询问Samjia会询问当前某个点的权值
现在,命运不可触摸,Samjia在苦苦追求真理,他希望得到你的帮助,看清,命运的,构造。
我们把第二种操作分块,然后可以处理一个块内所有操作对一个点的影响。
对第一种操作定期重构,那么一个点一定是最后一次赋值操作后,在一段时间区间里找第二种操作最小值,后者可以用根号做出来。
我们还要解决的问题是如何知道一个点能否到达另一个点。
可以bitset,但空间会爆。
那么可以对点分块,每次只需要管所有点对一个块内的点的联通性。
bzoj3709
把怪分为回血怪和扣血怪。
贪心杀光所有回血怪。
然后再贪心杀光所有扣血怪。
bzoj3502
经典的看做网络流然后数据结构模拟网络流的经典题。
2017.4.1
神tm鬼题,考场上想到了根本不敢写啊。。
我们观察到一个已放置的鞋柜,和一堆钦点了要放进去鞋柜的鞋。
假如这个鞋柜不在某个鞋上,一定可以左移或右移。
这就得到了鞋柜必在鞋上。
对于一对鞋[l,r],无论往哪个鞋柜,都需要付出至少r-l的代价。
当内部有鞋柜时,不需要付出额外代价。
否则, 选择往左往右最近的鞋柜来放。
知道这个可以DP了!
f[i,j]表示在第i只鞋放了鞋柜,已经放了j个鞋柜,目前最小的额外代价。
我们设一个G(i,j)表示有两个鞋柜分别在i和j中间无任何鞋柜会让中间的鞋对产生的额外代价。
n很小的时候可以考虑预处理,因为权值很大,所以用个数据结构保存关键点(有鞋子的点)和转折点(一对鞋子对会转而选择左边而不是右边的点),然后搞搞。
n很大的时候呢?先不管它,看怎么DP。
f[i,j]=min(f[k,j−1]+G(k,i))
f
[
i
,
j
]
=
m
i
n
(
f
[
k
,
j
−
1
]
+
G
(
k
,
i
)
)
n很大的时候这个DP好像就已经超时了!
不过我们可以来思考,对于一个固定的j,以及两个决策
k<l
k
<
l
,在j增加时G(k,j)和G(l,j)的增长比较。
每次都是会增加鞋子对,默认选右端,选右边的话显然增长一致。
但l大一些,一些鞋子对会更快进入转折点,从而减少增长。
因此决策k的G值增长会大一些!
那么我们可以考虑决策单调性啦,用单调队列保存决策,那么小的更容易冗余,于是放队头,队列需要维护决策函数图像交点单调。
这个交点又怎么求?正常的做法需要来个二分,那么问题还是如何迅速求G。
假设是求G(j,k),鞋子对是[l,r],需要满足j<=l<=r<=k
对于l-j<=k-r的,贡献为l-j
对于l-j>k-r的,贡献为k-r。
以第一个为例,即l-j<=k-r
移项得l+r<=j+k
可以根据l+r的值建主席树。
但我们还要满足j<=l<=r<=k
看起来还有两个条件,要写二维数据结构。
但是只需要满足l>=j,此时因为l+r<=j+k,必有r<=k
因此线段树下标是l(仅针对第一个式子),需要维护l的和以及个数。
出题人比较丧病,权值范围很大。
因此需要离散化,每次还需要二分找到对应主席树的根。
贼恶心!
2017.4.6
bzoj1099
分类讨论+数据结构
反正可以随便做的吧?
2017.4.7
bzoj1014
splay维护,询问的时候二分+hash
bzoj4811
一开始想的很naive要拆位做的。
实际上可以维护二进制数来表示一系列操作的影响。
大概就这样。
bzoj2096
枚举每个右端看看最左在哪里。
也就是两个指针走。
需要维护最大最小值,有加有删可以单调队列。
bzoj4726
二分一个x,然后做dp。
一个节点如果存在一个儿子子树能被全部感染而且该儿子子树的大小与该节点子树大小比例超过x,该节点也能被全部感染。
最后判断有没有一个能被全部感染的子树大小超过k。
2017.4.8
bzoj2302
充要条件,对于任意1<=j<=n满足
∑ni=1[ai>=j]<=n−j+1
∑
i
=
1
n
[
a
i
>=
j
]
<=
n
−
j
+
1
然后DP
2017.4.9
51nod1728
生成函数题。
可以看做深度最大不超过k的森林统计。
gk(x)表示深度不超过k的森林生成函数。
g0(x)就是个简单的EGF,
g0(x)=ex
g
0
(
x
)
=
e
x
gk(x)是深度为k的树的拼接,而深度为k的树是深度为k-1的森林加上一个根,所以有
gk(x)=exp(xgk−1(x))
g
k
(
x
)
=
e
x
p
(
x
g
k
−
1
(
x
)
)
然后做多项式求exp。
2017.4.10
bzoj4800
折半搜索裸题?
bzoj4709
设出dp状态。
不过可以发现s[j+1]一定等于s[i],而且选取的s0一定是s[i]。
对于同一个s[i],状态之间满足决策单调性,可以用单调队列优化。
2017.4.18
看了一下别省省选题
SDOIR1:
d1t1,做过了会写博客吧。
d1t2,用实边表示连接两个颜色一样的点的边,同理定义虚边。1操作对应access,2操作是虚边数量查找,3操作是子树一个点到根虚边数量最大值。只要维护出一个点到根的虚边数量就赢了。虚实切换时一个子树的这个信息受到修改,随手打颗线段树。至于如何快速找到往上第一个虚边,可以随手打个LCT,也可以随手树链剖分。
d1t3,用无限制减去不考虑质数。随手列个dp然后倍增+暴力卷积。
d2t1,01分数规划然后跑费用流。
剩余题不会。
HNOI:
d1t1,插入一个值找到前驱和后继,那么插在深度较大点下。手玩一下什么删最小最大,树的结构也只会有微小改变(比如删最小,它的右子树变成它父亲的左子树,其余都不变)
那么我们维护个ETT或LCT都能随便做。
d1t2,单调栈一遍求出每个位置往左往右第一个大于或小于。只需要统计多少(i,j)满足(i,j)内均小于或大于a[i]及a[j]。比如前者,那肯定存在left[i]>=l即+1。按left、right排序做可持久化线段树,大概脑补一下T_T。
d1t3,这个FFT裸题送的有点?你可以看做只有一个变,可以加上负数,c的范围显然在[-m,m],否则没可能最优。拆一下式子后,倍长做FFT,然后找到最小的位置,再去枚举一下c咯。
剩余题不会。
2017.4.20
zy大爷给看的题目。
一个序列定义高峰为高于两端的位置。
需要实时维护高峰的个数。
涉及的修改是区间加公差为正的等比。
一个高峰一定是一个极大上升子段的末端
将序列差分。
那么每次修改可以暴力找到负数位置。
设势函数为非高峰位置。
然后均摊显然是对的。
HNOI的抛硬币。
从b中选i个,从a中选j个,要求j>i。
那么现在改成从b中选b-i个,那么总共选了b-i+j>b个。
问题转化为从a+b个中选出超过b个。
把式子拆半,后半部分直接就是2的次幂(利用组合数性质)
先半部分项数不多,直接组合数取模。
51nod1592
莫队+数据结构方法显然
正解是分块,预处理块与块的贡献,然后每次询问再统计一波多余部分的贡献,多余部分之间的贡献,多余部分与块间的贡献,比较麻烦。
2017.4.23
bzoj3714
记录sum表示前缀和
每次可以知道sum[i]与sum[j-1]的奇偶性关系。
想要确定必须让所有前缀和的关系都明确。
最小生成树即可。
bzoj4434
第i个选手身价假设是xi。
我们把比赛之间身价和差分。
那么每个xi和-xi都会恰好出现一次。
把xi看做一条边,每条方程看做一个点。
这就是网络流流量平衡!
对于一条边二分上下界然后判断网络流是否存在可行流,即可。
bzoj4797
先假设我们能枚举环上相邻三点v、x、y,其中v和x、y均有连边。
怎么判断是否存在一个大于等于4的环覆盖这三个点呢?
首先x和y之间一定不能有直接连边。
然后假如我们删除了v,以及与v有直接连边相连的点(除了x和y),接下来只要x和y联通,就存在这样的环。
为什么呢,不会有多余的边吗?只要有多余的边,可以进一步把环缩小,直至缩至极小,由于x和y联通,删去了和v相连的,x和y没有直接连边,找出来的一定是大小至少为4的没有多余边的环。
但是枚举三个点是不现实的。
考虑这样一个算法。
枚举一个v,删去v以及与v相连的边。
那么便会形成一些联通块。
x和y显然要在一个联通块内。
但是我们不好处理一定不经过别的与v相连的点?
不需要保证这个,经过了也可以把环缩小。
那么考虑进行如下判断来判断是否有解:
是否存在一对x和y,均为与v相连的点,且x与y无直接边相连,x与y同时属于一个联通块。
发现那个x与y无直接边相连不是很好搞。
我们考虑一个命题:与v相连的所有点,若两点x与y同属于一个联通块,都有直接边相连。
该命题为假时有合法解。
我们可以计算出同属于一个联通块的有多少对,因为有直接边相连一定同属于一个联通块,若直接连边数达不到这个对数,则该命题为假。
于是一开始可以枚举每条边,再来枚举每个点,来计算计数器。
一旦能够判定一个点v是否存在于环中,便可以用n^2去找到合法x与y,进而找到合法解。
复杂度是O(nm)
湖南集训看到的题
找到一个x来最小化
∑ni=1(⌊aix⌋+ai%x)
∑
i
=
1
n
(
⌊
a
i
x
⌋
+
a
i
%
x
)
首先肯定有
ai%x=ai−⌊aix⌋x
a
i
%
x
=
a
i
−
⌊
a
i
x
⌋
x
我们来枚举这个x看看能不能快速计算这个式子。
显然可以枚举那个
⌊aix⌋
⌊
a
i
x
⌋
然后合法的ai是一段区间。
对a序列维护出桶和前缀和之类的东西,显然可以快速计算。
复杂度是调和级数。
2017.5.4
好久没来了QAQ
bzoj3637
维护两颗森林分别叫黑森林和白森林。
为了方便,我们规定,黑森林每颗树除了根一定都要是黑色,白森林类似。
这样修改和询问都很简单。
2017.5.26
bzoj4699
我们注意可以边取反然后从K开始做单源最短路。
Dij每个点只被访问一次,那么下水道中任意一点被访问时,这个下水道便不会再被使用。
我们考虑如何取出所有经过x的下水道。
先做出dfn。
假如下水道是A-B -> C-D,且
dfn[A]<dfn[B]
d
f
n
[
A
]
<
d
f
n
[
B
]
。
第一种情况是A在x子树B不在,第二种情况是B在x子树A不在。
第一种情况满足dfn[x]<=dfn[A]<=dfn[x]+size[x]-1,而dfn[B]>dfn[x]+size[x]-1。
第二种情况也有类似的式子。
前者我们用线段树维护dfn[A]在某区间时dfn[B]的最大值。每次不断取出最大值并删除直到发现最大值也在子树x内。
经过x当然有第三种情况,即A和B的lca是x,这个很容易直接挂在x上就行了。
于是我们维护一个堆实现Dij,里面存储边或下水道,如果是边,权值为K到起点最短路+边的长度,否则权值为下水道第一个被访问到的点+下水道权值。
对于下水道,我们可以暴力访问C-D上所有未被确定最短路的点。
每个点只会被确定一次,为了快速,用并查集来缩。
2017.5.27
bzoj4166
本质不同回文子串只有O(n)个。
做一遍manacher。
因此构造出回文树。
至于如何知道某个回文串是哪个点就用哈希。
最后按拓扑序倒扫。
2017.6.13
codejam 2017 QR 第四题。
车与象无法互相攻击。
一个后可以拆成一个车和象,恰好就是2分。
因此车和象独立,可以做两次最大匹配。
bzoj3837
m=2时k就能取到n/2。
所以答案的k>=n/2。
随机一个点它有1/2的概率在答案里。
因此随机几次,每次随机一个点,然后统计它在答案里的最大答案。
codechef xorsums
考虑前缀和。
si-sj在第k位上有没有1呢?
取决于(si-sj)/2^k是不是一个奇数。
假设si=t1*2^k+p1,sj=t2*2^k+p2。
如果p1>=p2,那么t1-t2是奇数则有贡献。
否则t1-t2是偶数才有贡献。
枚举k并维护线段树,大概复杂度两个log。
CF802N
是2000的范围的话,可以考虑这样建网络流。
S向i连流量1费用ai。
i向T连流量1费用bi。
i向i+1连流量正无穷费用0。
增广k次即可。
100000?
用线段树模拟网络流。
有点麻烦。
CF730E
讨论一下只有两种情况的对会对答案产生影响。
扫两遍做贪心即可。
codechef chefdoma
根号分治的做法很简单。
枚举主导数做出很多段,然后xjb做一下,是一个log的。
openJ_poj 1057 chessbord
行和列独立,分开做。
顺序扫+数据结构维护,贪心的做出一组可行最大匹配。
本题只需要考虑偶交替环,我们线段树优化构图,然后跑Tarjan。
TC SRM570 CurvyonRails
如果没有代价只求可行,你可以xjb连边网络流。
现在有了代价,每个点可以拆出横竖两个点,各连两条边,容量均为1,如果这个点有gay佬,其中一条边费用设为1。
2017.6.22
THUPC I题 SUM
我们定义gi表示任选i个的乘积和。
容易手玩出
fi=(−1)i−1∗gi∗i+∑i−1j=1(−1)j−1∗gj∗fi−j
f
i
=
(
−
1
)
i
−
1
∗
g
i
∗
i
+
∑
j
=
1
i
−
1
(
−
1
)
j
−
1
∗
g
j
∗
f
i
−
j
为了方便把-1的次幂放进g里
fi=gi∗i+∑i−1j=1gj∗fi−j
f
i
=
g
i
∗
i
+
∑
j
=
1
i
−
1
g
j
∗
f
i
−
j
定义g0=-1
−g0∗f1=gi∗i+∑i−1j=1gj∗fi−j
−
g
0
∗
f
1
=
g
i
∗
i
+
∑
j
=
1
i
−
1
g
j
∗
f
i
−
j
−gi∗i=∑ij=1gj∗fi−j
−
g
i
∗
i
=
∑
j
=
1
i
g
j
∗
f
i
−
j
设hi=-gi*i,则h=g*f,于是f=h*g^-1。
分治FFT求g,然后对g求逆,再做FFT就得到f。
SRM664 BearSorts
概率只与比较次数有关,最多比较O(n log n)次。
你很容易能瞎做出某个比较次数下有多少排列。
也很容易弄出前多少个固定是啥的有多少排列。
hackerearth Navi and Repeated Bracket Subsequences
这样的括号序一定开头是(结尾是)。
假定给了一个括号序,如何计算方案?
设fi表示前i个有多少方案。
fi=fi-1。
如果第i个是),那么枚举j,第j个是(,然后+=fj-1。
我们观察这个dp,可以写成下面的形式。
初始now=sum=1,因为第一个是(,now表示fi,sum就是sigma fj-1其中第j个是(。
每遇到一个(,就让sum+=now,否则now+=sum。
最终now>=sum,方案数为now。
这个过程可以逆着来,发现是欧几里得算法。
我们知道now=x,枚举sum,然后用欧几里得算法算出步数,找到最小的,然后可以构造出方案。
bzoj1443
把棋盘黑白染色,你会发现一个人走到格子的颜色总是一样。
然后你又能惊奇的证明,一定在最大匹配上的点作为起始位置一定GG。
这题就做完了。
2017.7.3
CF808F
先二分答案,特殊处理1,剩余的做二分图最小割(按奇偶性分二分图)
CC ALOST
算出多少前缀和需要是奇数,然后构造对应的01序列。
bzoj4231
拐点处的容易统计。
剩余问题变成一个到根路径有多少某字符串。
把询问串建AC自动机,然后在树上bfs,并在数据结构中fail树对应区间上加减,到某个点可以处理挂在上面的询问。
也可以大力树上SA?
CF283E
正难则反。
反过来的问题是啥啊?一个点x有t条出边贡献t*(t-1)/2!
一个点多少出边?扫描线做做吧。
CF809E
大力反演。
然后推出式子后枚举x并对x的倍数的点建虚树统计贡献。
bzoj3836
建出dfs树则最大深度不超过10。
因此三进制状压祖先的三种情况:选不选或有没有被覆盖。
然后按dfn顺序dp。
hdu5822
考虑本题对本质不同的定义,然后发现有两种本质相同变换:
1、树的子树交换。
2、环转圈,需要对应树同构。
先解决如果求树的本质不同染色方案。
做树hash,对于一个点的子树,若有某t个同构子树,这个同构子树染色方案为s,贡献应该是这样的问题:
1<=yi<=s
1
<=
y
i
<=
s
yi<=yi+1
y
i
<=
y
i
+
1
求y的方案数?
枚举yt的取值可以得到
∑si=1Ct−1i+t−2
∑
i
=
1
s
C
i
+
t
−
2
t
−
1
这个就是
Cts+t−1
C
s
+
t
−
1
t
不过注意s是模意义下的,直接做组合数真的对吗?
考虑lucas定理
Cmn%p=Cm/pn/p∗Cm%pn%p
C
n
m
%
p
=
C
n
/
p
m
/
p
∗
C
n
%
p
m
%
p
注意这里的t肯定比p小,t/p变成0,前面那个组合数一定是1,因此在模意义下做这个组合数没有锅。
还有个问题是s很大,组合数怎么求呢?
注意t和儿子个数同阶,假设O(t)计算组合数,总共不会超过O(n)。
可以处理出树的情况。
接下来解决一个问题,如何判断一个环套树是否存在转d圈这个置换?
一种可行的是再做树hash然后对破环序列再做hash,然后枚举d调和级数的时间去判断。
更简单的是对hash值做KMP,那么可以讨论最小border长度是不是d的因数。
然后知道这个就可以做Burnside了。
Rikka with Grid
维护bitset。需要特技分块卡内存。
hdu5991
考虑对于一个不完整三元组(即只有两条边),你有三种选择。
断掉其中一条边,或者补上缺的边。
于是可以3^10*n。
hdu5634
一个数不断取phi只有log次。
所以xjb维护颜色段。
CC Shubham Loves Maths
容易注意到f(ab)=f(a)b+f(b)a。
xjb转一下只需要求F的前缀和
考虑一个p^c的贡献是n/p^c。小的暴力,大的洲阁筛。
CF226D
每次都把负的行或列取反,总和至少增加一。
所以有限次一定会全部变正。
“玲珑杯”线上赛 Round #15 河南专场某题
注意到k+2~2k+1的灯都不能点。
举例说明,1号灯亮着需要1~k+1有奇数盏被点亮。
2号灯亮着需要1~k+2有奇数盏被点亮。
得到了k+2不被点。
同理我们还能得到2k+2~3k+2,点亮状态和1~k+1完全一致。
因为k+1号灯亮着需要1~2k+1有奇数盏被点亮。
k+2号灯亮着需要2~2k+2有奇数盏被点亮。
那1和2k+2的点或不点状态一致。
然后又有一段一定不点,一段和前面一致……一直这样下去。
因此我们考虑贪心,1~k+1需要奇数盏,我们肯定只点1盏。
点1盏会影响若干个,但是都是确定的,计算一下即可。
嘿嘿嘿的zy
操作1、2树剖
操作1、3树上带修莫队。
“玲珑杯”ACM比赛 Round #13某题
这些路径一定有公共交点。
枚举那个深度最小的公共交点。
怎么保证合法?一定要有至少一条路径以其为转折。
考虑容斥。
用全部都经过它的方案数,减去全部都经过它但是不以其为转折的方案数,即使答案。
“玲珑杯”线上赛 Round #17 河南专场某题
2^m枚举约束考虑容斥。
容斥系数可以打表。
bzoj4082
先变成一个序列。
考虑贪心,选了一个点下一个选的点确定。
想像成树,然后树上倍增,方便求一个位置跳不超过n要跳最多步数的最小值。
CF Hyper String
考虑设f[i,j]表示子序列当前最前面一个在i及以后,子序列长度为j能匹配到h的最右端点,就可以随便做了。
bzoj2734
考虑n=n’*2^a*3^b。
把它塞到矩阵中(a,b)这个格子里。
接下来变成矩阵两个格子有相邻边不能一起进集合。
注意到矩阵是log行log列,然后做状压DP即可。
bzoj3193
只考虑第二问。
按高度从大到小做,同一个高度可以做一个dp。
f[i,j]表示做到第i个空还剩j个。
总复杂度当然是n^2。
CF Metro Scheme
缩环树。
然后贪心一下?
2017.8.18
acp
一个集合n个元素(可重复)。
每次独立的加入一个新元素并询问选出k个的不同方案。
显然我们需要处理
G(x)=Πni=1(1+x+x2+……+xa[i])
G
(
x
)
=
Π
i
=
1
n
(
1
+
x
+
x
2
+
…
…
+
x
a
[
i
]
)
a[i]表示数字i的出现次数。
这个可以直接分治FFT,因为
∑ni=1a[i]=n
∑
i
=
1
n
a
[
i
]
=
n
还可以继续推下去
Πni=11−xa[i]+11−x
Π
i
=
1
n
1
−
x
a
[
i
]
+
1
1
−
x
Πni=1(1−xa[i]+1)(1−x)n
Π
i
=
1
n
(
1
−
x
a
[
i
]
+
1
)
(
1
−
x
)
n
分母显然有组合意义。设分子为F(x)
考虑
ln F(x)=∑ni=1ln(1−xa[i]+1)
l
n
F
(
x
)
=
∑
i
=
1
n
l
n
(
1
−
x
a
[
i
]
+
1
)
我们知道
ln(1−xi)=−∑j>=1xijj
l
n
(
1
−
x
i
)
=
−
∑
j
>=
1
x
i
j
j
因此可以调和级数的时间处理出ln F(x)。
再做多项式exp,那么你的预处理理论可以做到n log n。
现在考虑修改,相当于
G(x)(1−xa[i]+2)1−xa[i]+1
G
(
x
)
(
1
−
x
a
[
i
]
+
2
)
1
−
x
a
[
i
]
+
1
这个直接用竖式乘法和竖式除法来做即可,单次线性。
然后注意到本质不同的a[i]只有√n种,因此可以O(n√n)做完询问。
2017.8.21
hdu6057
设x=a|b,y=a^b,k=a&b。首先有两个性质,x^y=k,x&y=y(可代入四种情况验证)。我们可以不管i和j的具体,然后枚举x和y,就能固定出k,同时可以发现一对x和y对应的(i,j)对数有2^bit(y)种,bit表示1的个数,可以发现当y某一位是1时,原来的a和b这一位有一个1和一个0而且哪个在a哪个在b得到的x和y一样。
接下来我们把式子写成 c[k]=∑x xor y[x and y=y]∗a[y]∗b[x]∗2bit(y) c [ k ] = ∑ x x o r y [ x a n d y = y ] ∗ a [ y ] ∗ b [ x ] ∗ 2 b i t ( y )
然后可以发现,因为x&y=y,x^y=k,那么某一位x是1y是0,k这一位才会1,同时没0或没1k都没有1,那么就会有bit(x)-bit(y)=bit(k)。同样的反过来,如果bit(x)-bit(y)=bit(k),且x^y^=k,就一定有x&y=y(同理易证)。
式子继续写为 c[k]=∑x xor y=k[bit(x)−bit(y)=bit(k)]∗a[y]∗b[x]∗2bit(y) c [ k ] = ∑ x x o r y = k [ b i t ( x ) − b i t ( y ) = b i t ( k ) ] ∗ a [ y ] ∗ b [ x ] ∗ 2 b i t ( y )
接下来我们可以弄一个 a′[i]=a[i]∗2bit(i)∗x−bit(i) a ′ [ i ] = a [ i ] ∗ 2 b i t ( i ) ∗ x − b i t ( i ) , b′[i]=b[i]∗xbit(i) b ′ [ i ] = b [ i ] ∗ x b i t ( i ) ,即弄一个元素为多项式的多项式。那么 c[k]=[xbit(k)]∑x xor y=ka′[y]∗b′[x] c [ k ] = [ x b i t ( k ) ] ∑ x x o r y = k a ′ [ y ] ∗ b ′ [ x ]
2017.9.6
一个序列求
ai and aj
a
i
a
n
d
a
j
最大值。
可以按位贪心,如果这一位有>=2个1,把这一位是0的全部删掉。
2017.9.16
区间加法区间gcd
我好像太蠢了,其实可以注意到gcd(a,b,c,d……)=gcd(a,b-a,c-b,d-c……)
所以线段树维护一下就好了。
codechef twocomp
可以最小割,然后可以倍增优化连边。
2017.9.23
有一个完全图,试把该图点集分成两个不相交的集合A和B,定义d(S)表示找到一条边权最大的边使得两个端点都在S中,你需要最小化d(A)+d(B)
不妨认为d(A)>=d(B)
我们可以枚举d(A)然后二分d(B)。
用xi=1表示i点分到B集合,否则表示分到A集合。
如果一条边(i,j)边权大于d(A),那么xi xor xj=1。
如果一条边(i,j)的边权大于d(B),那么xi and xj=0。
然后我们可以用O(n+m)的2-sat问题(这题n^2条边因此有n^2个限制,单次2-sat复杂度n^2)。
关键是枚举这个d(A)需要n^2,这可不行。
我们称一条边上的权值如果有可能是d(A)那么这条边是候选边。
对于原图的一个偶环,可以断言其最小边不可能是候选边。
因为假若这条边两个端点都选入A集合,因为环长度为偶数,一定存在另一条边两个端点都选入A集合或B集合,而这条边边权显然更大。
对于原图的一个奇环,可以断言d(A)应大于等于其最小边的边权。
因为环长度为奇数,无论如何都会有一条边的两个端点被选入同一个集合。
现在,我们尝试找出候选边。
可以做一个最大生成树流程。
一条边如果是树边则它是候选边。
一条边如果是非树边但不形成奇环,它只能形成偶环,不可能是候选边。
一条边如果是非树边但形成奇环,把它加入候选边,然后因为其是d(A)的下限,所以可以退出最大生成树流程。
这样显然只有O(n)的候选边。
2017.12.12
bzoj4988
每次答案只会增加不超过2。
可以维护哈希来判断答案的增加。
一个图,从1->n,每次随机一个邻居,你可以走或不走,求最小期望时间。
首先可以明确一个策略,只有邻居到n的期望时间比自己小时才会走邻居。
把所有点分为白点和黑点,初始只有n为黑点。
我们令fx表示x->n的期望时间,dx表示x的度数,bx表示与x相连的白点数量,cx表示与x相连的黑点的f值和除以dx。
那么令gx=cx*dx/(dx-bx)。
我们每次找到一个g最小的白点,染成黑色,然后令fx=gx,并更新其所连向的白点的g值。
直至染色完成,得到f1。
为啥是对的?
讨论对于x和y,fx>fy,可以发现x不会比y先染成黑色。因此我们最后一定是按照f的大小顺序染色的。
一个排列,若干次询问包含区间[l,r]的最小区间[L,R],[L,R]值域连续。
用经典题思路做,考虑分治,处理出合法左端及对应最小合法右端和最大合法右端,询问很好解决。
2017.12.26
bzoj4298
想了很多奇怪的思路。
其实就是我们设f[i][j]表示点i在第j张图的联通块编号,然后把f[i][]哈希一下就好了,两个点在d张图中都联通代表它们哈希值要相同。
2017.12.27
loj6222
发现一个满足题目的数可以表示成
a2∗b3
a
2
∗
b
3
其中
μ(b)!=0
μ
(
b
)
!
=
0
。
因此式子为
∑n13b=1μ2(b)∗b3∗∑a2∗b3<=na2
∑
b
=
1
n
1
3
μ
2
(
b
)
∗
b
3
∗
∑
a
2
∗
b
3
<=
n
a
2
这就非常好算了。
2018.3.26
IOPC14E
一颗点权树,点
i
i
权值为,有若干次修改后若干次询问。
修改形如给一条链
p1,p2……pk
p
1
,
p
2
…
…
p
k
对于
1≤i≤k
1
≤
i
≤
k
有
vpi+=iXRi
v
p
i
+
=
i
X
R
i
X是该次修改给出的量,R为常量。
询问形如一条链的和。
设
deepi
d
e
e
p
i
表示点
i
i
的深度。
以自上而下的修改一条祖先后代链为例。假设修改起点深度为。
不妨设
vi=Ai∗(deepi∗Rdeepi)+Bi∗(Rdeepi)
v
i
=
A
i
∗
(
d
e
e
p
i
∗
R
d
e
e
p
i
)
+
B
i
∗
(
R
d
e
e
p
i
)
那么对于
i
i
的修改量为
可以发现
Ai+=XR1−d,Bi+=(d+1)XR1−d
A
i
+
=
X
R
1
−
d
,
B
i
+
=
(
d
+
1
)
X
R
1
−
d
。
因此修改变成了对
Ai,Bi
A
i
,
B
i
的简单加法。
那么问题迎刃而解。