懒得写这么多博客了。。
开个坑记录一下
也许写着写着就断更了,那么就断更了再说吧
都是bzoj的题号,如果不出意外的话应该是没有别的oj的题的
大概说一下文章格式
简单的:题目
有点困难的:*题目
看了题解的:**题目
然后你可能会发现全部都是第三种QAQ
**4377: [POI2015]Kurs szybkiego czytania
并不是很会。。
容易发现,每一个数都会出现且恰好出现一次。。
然而我不是很知道这个有什么用2333
这个的用处在于,以
i
i
i开头的序列是唯一的
因此,对于每一个开头
x
x
x,我们可以分别考虑
我们可以得到
m
m
m个方程,列出方程组,解出来
x
x
x的并集就是可行解了
注意最后不足
m
m
m个的数
并集的话,可以用线段树维护一下,或者排序后直接差分也行。。
但是有更巧妙的方法,就是把并集转化为补集的交集
也就是求出不合法的情况,那么不合法就是交集了
然后用总的减去即可
3734: [Ontak2013]Miny
和之间做过的5017: [Snoi2017]炸弹就是一样的
可以直接用线段树优化建图来做,那么时空都是
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的
你或许也可以加个random_shuffle,然后直接暴力做,每一次跳一段
但是今天想想,有更优秀的做法
就是维护单调栈,从左往右和从右往左各扫一次
单调栈维护可以炸到的范围递减的地雷
因为如果后面有比他炸得更远的,连后面的就可以了
这样边数就是
O
(
n
)
O(n)
O(n)的了
**3106: [cqoi2013]棋盘游戏
首先,玩几个数据可以发现,白棋没有任何逼死黑棋的方法
也就是说,除了一开始获胜,白棋没有任何赢面
看着都知道技能被完爆啊
炉石传说没有完爆
相反,黑棋,只需要走到白棋的四周
(
−
1
,
−
1
,
)
(
−
1
,
1
)
(
1
,
−
1
)
(
1
,
1
)
(-1,-1,)(-1,1)(1,-1)(1,1)
(−1,−1,)(−1,1)(1,−1)(1,1),就可以根据白棋的走法逼死白棋了
因此,BLACK一定会赢
进一步分析,白棋走到中心是他苟活的最优策略,最多可以苟活
2
∗
n
2*n
2∗n轮
然后黑棋也走过去,只需要
n
/
2
n/2
n/2轮,白棋在多余的时间乱转一下就好,那么这个时间也是
n
n
n轮,发现,最差情况答案不会超过
n
∗
3
n*3
n∗3
考虑分类讨论,发现情况有点多。。应该很容易搞漏。。
发现数据范围很小,考虑爆搜,显然是一个白棋取max,黑棋取min的记忆化搜索
按照常理设计记忆化,
f
[
o
p
]
[
r
1
]
[
c
1
]
[
r
2
]
[
c
2
]
f[op][r1][c1][r2][c2]
f[op][r1][c1][r2][c2],发现状态很少,但是没法记忆化,出现环就凉凉了
看了下题解。。发现其实我们只要把步数也丢到状态里面就好了
瞬间感觉自己是个傻逼。。
但回头一想,自己以前对于有环的搜索似乎都不会记忆化。。一直认为无法记忆化。。
把步数放进状态里面很关键,这个要记住
那么复杂度就是
O
(
n
5
)
O(n^5)
O(n5),可以通过
3799: 字符串重组
这种字典序比大小的,往往就是寻找最大的LCP,比下一位
这题可以采用一样的套路
枚举最大的LCP是什么,那么下一位就找一个比T大的最小的,然后后面按字典序最小来排就可以了
直接这么写就是
O
(
n
2
)
O(n^2)
O(n2)的,已经可以通过
但是可以发现,LCP越大,答案肯定越优,因此,只需要先找到最大的LCP就行了
时间复杂度可以做到
O
(
n
)
O(n)
O(n)
但是我比较懒。。还是写了
O
(
n
2
)
O(n^2)
O(n2)的做法
**3308: 九月的咖啡店
很迷的一个题。。
不难想到按质数来考虑。。
拆了个结论,就是一定是一个质数一组
然后玩了一下,
p
1
=
5
,
p
2
=
7
,
n
=
35
p_1=5,p_2=7,n=35
p1=5,p2=7,n=35
可以发现
25
+
7
<
35
25+7<35
25+7<35
然后就不会了。。
看了题解
发现有两个结论:
1.最多只有两个质数一组
2.如果有分组的话,两个质数,一个大于
n
\sqrt{n}
n,一个小于
n
\sqrt{n}
n是最优的
如果知道这个结论就很好做了。。
按
n
\sqrt{n}
n分成两组,费用流就好了。。
但是这两个结论怎么证呢。。
**3875: [Ahoi2014&Jsoi2014]骑士游戏
以前做过。。然而还是不会做
容易想到DP,但是发现环的情况无法转移,然后GG
解决的方法是可以类似SPFA的转移,没更新一个就尝试更新所有别的节点
时间复杂度不知道,但是跑得飞快。。
还有另外一种做法
先假设一开始所有人都用魔法
然后类似dij的扩展
f
i
f_i
fi表示
i
i
i这个怪兽打完的最小代价
然后肯定先扩展
f
f
f最小的
当一个点,他用普通攻击变出来的所有点,都被扩展过了,那么他就可以算出新的答案了,和之前比较一下哪个优就好了
否则,如果有任何一个点没有扩展过,那么都不可能更新
一开始想过这个,但因为一些奇奇怪怪的原因否掉了。。
感觉自己经常遇到这种东西就会想错。。但实际上他是对的
然后不断更新即可
时间复杂度就是稳定的
O
(
n
l
o
g
n
+
m
)
O(nlogn+m)
O(nlogn+m)了
第二个方法应该是要想出来的。。还要继续努力啊
第一个方法应该处理有环的DP十分常用,把DP式写出来以后,应当多尝试一下转化为最短路模型来跑啊!
3444: 最后的晚餐
比较简单的题。。
一开始看错了。。以为是个环。。
然后又看了一次才发现TAT
既然不是环,那么就一定不能出现环
然后一定不可以出现度数大于3的点
直接dfs
对于每一个联通块,一定是一条直链
如果是一个点,那么就是一种方案
否则就有两种方案
最后乘上联通块的阶乘就行了
3440: 传球游戏
一开始瞎搞。。以为直接找环就完事了。。
记忆化搜索一下,
f
i
,
j
f_{i,j}
fi,j表示从j方向到i搜过没有
发现还有别的情况
就是从一个方向进入,走一圈后从另外一个方向出来
尝试fix一下这个搜索。。加了一维k表示从哪里进来
发现并没什么用。。
然后就把这个智障做法丢掉了
拆成两个点建图
考虑直接连出
f
i
f_i
fi,表示这个状态的下一个是谁, 容易发现,一个点只有一个出度,反过来就是一个换套树森林
把环找出来,上面所有点都是合法的
然后剩下的森林,显然可以发现从环上的点开始遍历就是最合法的
然后能到达两次的点当且仅当有一个点可以到达他另外一个点
于是dfs一下就好了
3441: 乌鸦喝水
以前做过一次。。然而还是不知道怎么做
随便搞搞,写了个奇奇怪怪的线段树就水过去了23333
时间似乎很慢。。
这里提供一个可能不能过的做法,但是就是水过去了。。可能不知道怎么卡吧
每个点维护四个值:
x
x
x还要多久就被喝完了,
x
x
xx
xx前面有多少个数,
i
d
id
id编号是什么,
c
c
c前两个东西的差是什么
当一个数的
c
<
0
c<0
c<0的时候,他就被喝完了
把它删掉,然后更新后面所有数的
x
x
xx
xx
删的顺序显然很有讲究,反应在c的排序上,具体来说,就是,当c都是负数的时候,返回id小的
否则按
c
c
c为第一关键字,
i
d
id
id为第二关键字排序
然后每一轮,看剩下多少个数
t
o
t
tot
tot,答案就加上
t
o
t
tot
tot
考虑如何用线段树优化这个过程
直接打
l
a
z
y
lazy
lazy是不行的,因为这个排序有两个法则
你一加,可能会使负的变为正的/正的变为负的,从而影响判断
这个一定要记住,当大小判断会随着值的不同而不同的时候,打
l
a
z
y
lazy
lazy要特别注意
那怎么办?
解决方法就是,保证不会出现这一情况
至于怎么保证,这里就懒得写了。。如果有人想知道再来找我吧。。
可能会牺牲很多复杂度,但是他就是过了
话说Rose有更为简单的方法
我们每一次找到要和次数最少的
我们每一次计算出,他变为0的时候我们跳到了哪里
维护一下第k个还没喝的在哪里就可以了
感觉简单很多
3579: 破冰派对
TYB告诉我这是一个搜索题。。想了一下就直接开始了
先把有多个大于1的连通块判掉
那么任务就只剩下一个连通块了
直接爆搜
0为参加派对,1为工作人员
如果一个位置填0,那么就要把他四周所有的人变为1
如果一个位置填1,则要满足之前所有人到他都有边,开个bitset维护一下就好了
最后判掉全0/1的情况就行了
4532: [BeiJing2014 WinterCamp] 珠链
因为
R
−
L
R-L
R−L很小
因此,我们可以暴力枚举每一段有多少个
可以发现,段数不可能超过
52
52
52
TYB说他写的就是
(
R
−
L
)
∗
52
∗
n
(R-L)*52*n
(R−L)∗52∗n,然而我并不知道他是怎么写的2333
似乎写了点单调队列什么的。。
你会发现,如果个数确定了,那么每个数的对应关系是一样的,按余数分组即可
因此,可以枚举起点,然后把终点不断右移,最后切成段即可
具体来说,维护一个数组
t
i
,
j
t_{i,j}
ti,j表示余数为
i
i
i,字母
j
j
j出现了没有
不要暴力初始化,否则复杂度就不对了。。
时间复杂度是
O
(
n
(
R
−
L
)
)
O(n(R-L))
O(n(R−L))
**4204: 取球游戏/2510: 弱题
双倍经验然而并没什么用
不会啊这个。。
容易想到递推式
f
i
=
f
i
−
f
i
m
+
f
i
−
1
m
f_i=f_i-\frac{f_i}{m}+\frac{f_{i-1}}{m}
fi=fi−mfi+mfi−1
可以构造一个
n
2
n^2
n2的矩阵去优化这个东西
直接做复杂度是
O
(
n
3
l
o
g
n
)
O(n^3logn)
O(n3logn)的
可以看出,这个矩阵似乎很循环的样子,于是被称为循环矩阵(大雾)
循环矩阵大概就是行向量的每个元素都是前一个行向量各元素依次右移一个位置得到的结果
有性质,循环矩阵乘循环矩阵还是循环矩阵
显然,一个循环矩阵可以用第
1
1
1行表示出来
于是我们就可以把矩乘优化为只做一行,那么就是
O
(
n
2
)
O(n^2)
O(n2)的了
于是总的复杂度就是
O
(
n
2
l
o
g
n
)
O(n^2logn)
O(n2logn)
*3876: [Ahoi2014&Jsoi2014]支线剧情
每条边都要走一次
可以看做是下限为
1
1
1,上限为
i
n
f
inf
inf的边
然后跑满足下界的费用流就好了
复习了一下上下界有关的,感觉又有了新的理解
3786: 星系探索
容易想到,用欧拉序来搞这个东西
然后进来为正,出去为负
然后就可以变成子树和了
所有操作用splay维护即可
花了
1.5
h
1.5h
1.5hrush了一波,不知道在考场是否可以在1.5h弄完
并且考场还要拍,感觉有点慌
4229: 选择
我真是个傻逼。。以前做过两次还是不记得。。
这题和4998: 星球联盟是一样的。。
当时的做法是倒着加边,然后缩起来
然而不记得了。。
写了个树剖,每一次给路径++,如果有任何一条边的值小于2就不合法
看起来思路是一样的,但是复杂度多了两个log
但是似乎线段树修改/查询的时候,如果这一段最小值已经大于1了,那么就直接返回,那么复杂度就是一个log了
但是还是没有用并查集来的优秀
*4230: 倒计时
之前做过一次,但是还是觉得很巧妙
可以发现,每次取最大的减是没有问题的
每一次,我们把一个数拆成两个部分
最高位和后面的
记录两个状态,前面的位最大是什么,已经当前要处理的数是什么
然后返回的时候返回退位和次数即可
容易发现,这样做的状态并不是特别多,可以通过
**4664: Count
先排序,然后从大往小
一个朴素的想法是直接DP
f
i
,
j
,
k
,
l
f_{i,j,k,l}
fi,j,k,l表示填到第
i
i
i个数,分成了
j
j
j段,当前的和为
k
k
k,左右端点还有
l
l
l个
每一次可以讨论转移,连接两段/放在一段后面/独自为一段,当头当尾
然后加上他的贡献
但是显然可以发现,这个DP的状态数已经是
O
(
n
3
L
)
O(n^3L)
O(n3L)了
虽然是
O
(
1
)
O(1)
O(1)转移,然而还是会T
然后就不会了
题解很巧妙
我们考虑,如果我们没有减法,那么值域就可以变为L,就可以通过了!
有一个很巧妙的计算贡献方法,我们从小到大加入一个数
然后把贡献拆成若干段,每填入一个数
i
i
i,就暴力把端点的数到
i
i
i的差先加上
那么,以后所有要算的,都可以变为和
i
i
i的差,那么就之和相邻的数有关了
因为数是递增的设
a
<
b
<
c
a<b<c
a<b<c,所以对于一个差来说,
(
c
−
a
)
=
(
b
−
a
)
+
(
c
−
b
)
(c-a)=(b-a)+(c-b)
(c−a)=(b−a)+(c−b)
因此这么做显然是对的
这个把贡献拆开的思想很妙!这个想办法去掉加法的思想也很妙!
一定要记住哇
*3135: [Baltic2013]pipes
首先
m
3
/
s
m^3/s
m3/s是一个单位,不是数值。然后d,p的用处只是告诉你是两倍关系
先考虑一棵树怎么做,显然dfs一下就可以了
发现根不合法怎么办?凉凉咯
那么如果有环会怎么样?
你会发现,如果这条边连的是奇偶性不同的点,那么这条边就是废的
否则,你可以用这条边来调整根的值,讨论一下,都是奇/都是偶是不一样的
然后调整完以后再dfs一下就可以了
最后,如果树根是合法,但是有边连接奇偶性不同的点,那么就有无限种情况,输出0就行
哦,还有,一个联通块里面有两个环,那么一定是不合法的
然后就没什么了
一开始想漏了很多情况,WA了很多发。。
*4035: [HAOI2015]数组游戏
先写了个暴力,尝试发现每一个情况SG的规律,然而发现并没什么用。。
于是冷静分析了一波
猜想每一个1是互不影响的
事实上就是这样
听说, 所有的有向图游戏的和都等于它包含的各个子游戏SG函数的异或和
应该就是这个意思
知道了这个以后,再冷静分析一波,发现对于
n
/
x
n/x
n/x一样的,
S
G
[
x
]
SG[x]
SG[x]都是一样的,然后暴力做就可以了
分块套分块,听说复杂度是
O
(
n
3
4
)
O(n^{\frac{3}{4}})
O(n43)的
3137: [Baltic2013]tracks
挺简单的题
可以知道,最后走的人是谁
然后我们直接让这个人有所有和他连通的点
然后把这些点变成另外一个人的
然后换另外一个人走
不断重复此过程,知道全部走完为止
考虑优化这个过程,其实只需要开两个队列就好了,当一个人扩展的时候把另外一个人可以扩展的点加入另外一个队列中
两个队列相互换着走就行了
4169: Lmc的游戏
虽然做出来的。。但是总感觉哪里怪怪的
一开始想二分,然后二分着二分着就把二分删掉了。。
先考虑最大值怎么做
我们记录一个ans,表示至少要多少个比mid大的
如果当前节点是先手动,那么我们只需要保证最小的子树得出来的答案比mid大就行了
否则,我们需要保证所有子树得出的答案比mid大
就这么递归,到叶子就
a
n
s
+
+
ans++
ans++
然后考虑最小值,发现这个状态似乎不好用
转化为至少有多少个要比mid小
然后把操作反过来
如果是先手动,那么就保证所有子树得出来比mid小
否则,只需要保证最小的子树得出来比mid小就好了
额。。写出来似乎还挺有道理的啊
然后这个mid可以丢掉,直接记录ans就好了
4105: [Thu Summer Camp 2015]平方运算
直接猜想有循环节
打出来最大的61,LCM炸爆了,然后发现打错了。。
又打了一次,最大60,LCM也是60!
然后进入循环节的话最大是4还是5的样子
然后线段树维护一下就可以了
想了一下,发现那个60没法去掉,那么就只可以
60
m
l
o
g
n
60mlogn
60mlogn
4149: [AMPPZ2014]Global Warming
我的做法被卡常数了23333,那么就不管了
显然先用单调栈什么的求每个数作为唯一最大/最小值的区间
然后就是要搞一个交集
因为这个是唯一最大/小,所以每一个数只会被覆盖一次
线段维护区间+1,-1,然后线段树上二分一个>=2的值就好了
但是似乎并不能卡过去QAQ
看了下Rose的做法,似乎常数小点?
就是因为一定有一个贴边界,因此,可以暴力枚举右边界贴谁的
按顺序加入,找一个最小的左边界就好了
还有一个正解做法,不想看了
1304: [CQOI2009]叶子的染色
一开始猜了一个结论,根选谁都没有关系。。
但是想着想着把这个结论忘了。。
事实上这个结论是对的,因为不存在两个颜色一样的相邻点
然后简单DP就好了,每一次把父亲染成节点数多的颜色就行了
似乎拖更了。。
*3997: [TJOI2015]组合数学
似乎写出了一个不一样的做法2333
网上的做法用的都是Dilworth定理
把问题转化为最大独立集,然后DP
然而我并没有想起这个定理(虽然之前讲过一次)
考虑直接贪心,因为每个点只可以从上/左过来
因此,我们可以记录一个数组
b
b
b,表示走完第
i
i
i行,
(
i
,
j
)
(i,j)
(i,j)这个位置至少会有多少人
每一个格子,先优先从上往下走,如果不够,就找左边要。
实现的话,记录一个mx,表示要往右走多少个就好了
这个贪心策略显然是正确的,然后就没什么了
然后最后一行
b
b
b数组加起来就是答案了
是不是感觉简单易懂
一开始因为数据范围看成了4000,我也不知道为什么,MLE了几发,开了滚动才过。。
2728: [HNOI2012]与非
玩一玩可以发现,这个操作是无敌的。。什么位运算都可以被他弄出来
然后又玩了一下,发现只有被覆盖集合一样的1要一起选,别的都可以独立
又玩了一下,发现可以一位一位做
又玩了一下,就AC了
2671: Calc
之前做过一个类似的题。。
准确来说基本都是一样的
需要知道,如果ab互质,那么
(
a
+
b
)
(a+b)
(a+b)与
a
b
ab
ab互质
然后把gcd提出来,可以得到
(
x
+
y
)
∣
d
(x+y)|d
(x+y)∣d
(
x
,
y
)
=
1
(x,y)=1
(x,y)=1
然后大力反演一下,随便加点剪枝就可以AC了
2665: [cqoi2012]编号
只要选出任何5位都不一样就行了。
发现大力爆搜,然后记忆化剪枝一下就好了
代码比较恶心。。纠结了一会有没有更优的方法
3712: [PA2014]Fiolki
启发式合并模拟一下就可以了
如果你注意到这是一棵树就更简单了。。按LCA深度为第一关键字,反应顺序为第二关键字,然后做就行了,然后也是模拟一下就可以了
2878: [Noi2012]迷失游乐园
树的话
考虑算出每个点作为根的答案
先得到1号点为根的答案
然后dfs一下可以得到全部的答案
考虑环的情况
算出环上每个点的答案
环上的点可以暴力枚举走到了环的哪一个点来计算
然后用同样的方法dfs一下可以得出全部答案
注意一些细节就行了
时间复杂度可以做到
O
(
n
+
k
2
)
O(n+k^2)
O(n+k2)
k
k
k是环上点的个数
但是考虑到这样代码复杂度会变高。。细节会变多
因此,写一个
O
(
n
k
)
O(nk)
O(nk)就好了。。
2326: [HNOI2011]数学作业
基础的矩阵乘法居然忘了。。
按位数加进去,那么每一次就是乘
1
0
n
+
x
10^n+x
10n+x
居然一直不知道
x
x
x该怎么维护。。
其实也是丢到矩阵里面就可以了
设原来的矩阵为
(
S
,
A
,
1
)
(S,A,1)
(S,A,1),那么转移矩阵每一次让
S
+
A
S+A
S+A,
A
+
1
A+1
A+1,
1
1
1不变就行了
显然可以构造矩阵满足这一点。。
然后就没了
1237: [SCOI2008]配对
这是一个结论题呀。。
一开始猜了一个结论,就是排序以后,配对距离不会超过1
然后似乎随便YY了一个例子就GG了
开始思考有没有别的做法
然后Rose告诉我,他记得结论是排序以后,配对距离不会超过2,摔)
具体怎么证明??
有一个很重要的限制是互不相同
4的话可以用穷举法。。 更大就不会了,猜想法?
如果有这个结论,简单DP就可以了
f
i
f_i
fi表示前
i
i
i个数的最小值即可,分3个情况转移
**2437: [Noi2011]兔兔与蛋蛋
并不会做这个。。
建图很妙
按原图的黑/白来建图,一开始所在的格子为黑,然后相邻的黑/白连边
一个点可以连边当且仅当我们可以到达这个点
这个奇偶性判掉就可以了
可以观察到不会出现环的情况,因此,移动过后,一个点的黑白状态变化也没有影响,直接把这个点删掉就可以了
至于怎么判断,就是二分图博弈的问题了
3307: 雨天的尾巴
可以差分,然后线段树合并搞一搞
这样时空都是
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)的
也可以树剖,然后维护个set扫一扫
这样时间是
O
(
n
l
o
g
2
n
)
O(nlog^2n)
O(nlog2n),但是空间时
O
(
n
)
O(n)
O(n)的
4667: 小y的密码
打一个表,发现把一个序列排序以后,本质不同的只有
5
w
5w
5w多个
因此,可以暴力枚举哪一位开始不一样,然后如果可以随便填,就暴力枚举这
5
w
5w
5w个排列一下就好了
枚举的话,我写的是直接枚举最小的是什么。然后次小的…如此类推
2698: 染色
求一下每一个点期望有多少概率是黑色的
这个的话,扫不到的概率的
m
m
m次方就好了
概率可以用区间个数/总区间个数
区间个数显然是一个等差数列求和
随便搞搞就好了
**2597: [Wc2007]剪刀石头布
并没有想到减去不合法的情况。。然后想了半天还是毫无想法QAQ
如果想到不合法的情况,就好做了
首先,三元组的个数是
C
n
3
C_n^3
Cn3
可以发现,一个三元组不合法,一定有且只有一个点的入度为
2
2
2
那么不合法的个数就是
C
d
u
[
x
]
2
C_{du[x]}^{2}
Cdu[x]2
写成一般形式就是
d
u
[
x
]
×
(
d
u
[
x
]
−
1
)
/
2
du[x] \times (du[x]-1) / 2
du[x]×(du[x]−1)/2
可以发现,这东西的增长速度是单调的
根据套路,差分一下建图就可以了
最后费用流即可
正难则反很妙,计算不合法的方法也很妙,这个一定要记住哇!
也可以转化为,有一堆和确定的变量,然后你要使得他们的平方和最大
每次调整不平衡度即可,可以用迭代法来做
1449: [JSOI2009]球队收益
和上一题一样做就好了
考虑到有两个变量都会造成影响
可以把式子写成
C
i
x
2
+
D
i
(
d
u
[
x
]
−
x
)
2
=
(
C
i
+
D
i
)
x
2
−
2
D
i
x
C_ix^2+D_i(du[x]-x)^2=(C_i+D_i)x^2-2D_ix
Cix2+Di(du[x]−x)2=(Ci+Di)x2−2Dix
把这个式子写出来发现也等价于全部假设为输,然后调整
不难发现,这玩意的对称轴是
D
i
C
i
+
D
i
\frac{D_i}{C_i+D_i}
Ci+DiDi
显然小于
1
1
1,也就是在
x
>
1
x>1
x>1的时候是单调递增的,差分以后也单调递增
但因为这个不像上一题一样可以图全部建出来,因此把
x
x
x变为多赢了多少把,只建
m
m
m条边即可
如果写迭代可以跑得更快。。
**4405: [wc2016]挑战NPC
建图十分巧妙!!
在我知道这是一个一般图最大匹配的情况下都不知道怎么建
把一个箱子拆成三个点,互相连边
然后每个点向可以到达的三个点连边
答案是最大匹配-n
题目保证了至少有一个方案
因此,匹配过后,除了每一个点的匹配,所有半空盒子都会贡献且仅贡献1的匹配数
建图很妙啊!
然后跑一个一般图最大匹配就可以了
如果要方案的话,要从后往前匹配,以保证每个点都有匹配
1019: [SHOI2008]汉诺塔
简单题搞了半天。。
首先,按照汉诺塔一贯的规律来设立DP
我们每一次一定要把前
i
−
1
i-1
i−1个东西全部搬走才可能会搬第
i
i
i个数
不难想到这么设计DP
f
i
,
j
f_{i,j}
fi,j:有i个盘子在第j个柱子上要多少步
然后发现没法转移
g
i
,
j
g_{i,j}
gi,j:有i个盘子在第j个柱子上最后在哪里
然而我在这里卡了半天。。
主要原因是想着想着,就把条件变成了不用上次一样的操作。。明明看题的时候都不是这样的
然后发现,可能会出现A–>C,C–>B,B–>A的情况
然后自闭了
忽然想起来这样无解。。才意识到把条件搞错了。。
那么就很好DP了,一定是
i
i
i被移到空塔,再讨论一下就可以转移了(大雾
3450: Tyvj1952 Easy
似乎做法复杂了。。
先说说题解的做法,就是直接DP
f
i
f_i
fi表示
[
1
,
i
]
[1,i]
[1,i]的答案
然后再记录一个当前的期望长度
L
L
L
分三个情况转移就可以了
如果是x,那么就是
L
=
0
,
f
[
i
]
=
f
[
i
−
1
]
L=0,f[i]=f[i−1]
L=0,f[i]=f[i−1]
如果是o,那么就是
f
[
i
]
=
f
[
i
−
1
]
+
2
L
+
1
,
L
=
L
+
1
f[i]=f[i−1]+2L+1,L=L+1
f[i]=f[i−1]+2L+1,L=L+1
否则,就是上面两个取平均
我的做法是把
x
2
x^2
x2看做是点对
那么就是问期望点对
在每一个点统计贡献,维护一个前面期望有多少个点即可
要正着做一次反着做一次才可以,似乎复杂一些。。
3442: 学习小组
挺简单的题
容易发现,唯一不好解决的是必须有一个,但是又可以没有
容易想到,建多一个课程就好了,一个学生可以报
k
−
1
k-1
k−1次,然后怎么报代价都是0
然后剩下的,就是拆点费用流的问题了
**2039: [2009国家集训队]employ人员雇佣
米拉奇战记真好玩
并不会做
学习了一下二元建图的方法
具体来说,一个割对应一个方案
然后一个点一般和原/汇的连边代表选/不选
在这题里面
在这题里面,可以得出方程:
e
=
a
i
e=a_i
e=ai
f
=
a
j
f=a_j
f=aj
a
+
b
=
2
e
i
,
j
a+b=2e_{i,j}
a+b=2ei,j
a
+
c
+
f
=
3
e
i
,
j
+
a
j
a+c+f=3e_{i,j}+a_j
a+c+f=3ei,j+aj
b
+
d
+
e
=
3
e
i
,
j
+
a
i
b+d+e=3e_{i,j}+a_i
b+d+e=3ei,j+ai
于是就可以得到每一条边的流量啦!
跑最小割就好了
**3504: [Cqoi2014]危桥
大领主真厉害
时隔一年半做这题。。发现仍然不是很会做
首先,一个比较显然的做法是
S—>a1,b1
a2,b2---->T
但是你会发现,不仅会出现a1—>b2的情况
还可能会出现一个危桥从两边各走了两次的情况
怎么办?
解决方法是b1,b2反过来再跑一次
那么第二个情况显然会被判掉
至于第一个情况,如果反过来也是合法的,那么一定是合法的
证明的话感受一下?(雾
*2121: 字符串游戏
昨天晚上想了两个DP,然而因为复杂度太假都丢掉了。。
看了下题解,发现题解的复杂度居然和我是一样的23333
时间复杂度似乎都是
O
(
n
3
∗
∣
S
∣
∗
∣
p
∣
)
O(n^3*|S|*|p|)
O(n3∗∣S∣∗∣p∣)这怎么能过啊。。
感觉就是这出题人在搞我。。让我看题解
然后就很开心地把两个做法都敲了一次,都过了
两个做法都是受到别的题的启发
核心思路就是求出
f
i
,
j
f_{i,j}
fi,j能不能全部被删掉
一个是类似于bzoj5128的转移,
f
i
,
j
f_{i,j}
fi,j表示能不能搞出来
每一次转移有两种,第一种是分成两段来合并,这里是
O
(
n
3
)
O(n^3)
O(n3)的
第二种是,考虑到每一段至多会被插入一个串,显然如果有两个串相互交叉是删不掉的
因此,可以暴力枚举这个串是什么。与bzoj5128不一样的是,这个串我们匹配到第几位是不知道的,因此还要DP一下现在匹配到第
i
i
i位行不行,那么这里的复杂度就是
O
(
n
3
∗
∣
S
∣
∗
∣
P
∣
)
O(n^3*|S|*|P|)
O(n3∗∣S∣∗∣P∣)
第二个是类似于bzoj3255的转移,维护两个数组
f
i
,
j
f_{i,j}
fi,j表示
[
i
,
j
]
[i,j]
[i,j]能不能删完
g
i
,
j
,
l
,
k
g_{i,j,l,k}
gi,j,l,k表示
[
i
,
j
]
[i,j]
[i,j]这一段,能否删剩第
l
l
l个串的前
k
k
k个
然后
f
f
f个
g
g
g互相维护即可,这个做法网上太多的。。这里就不赘述了
话说我个人认为第一个做法是更好想的,但是似乎网上的人写的都是第二个。。这是怎么回事啊QAQ
*2287: 【POJ Challenge】消失之物
首先,比较显然的想法,是统计一个前缀答案,一个后缀答案
然后每个点FFT一下,就可以得到一个
n
2
l
o
g
n
n^2logn
n2logn的做法
这样做常数很大,你还可以分块来做。。复杂度是
n
2
n
n^2\sqrt{n}
n2n
然而这些都不是优秀的做法
随口猜想一下,背包可以撤销
羊告诉我这样就是对的。。
理由很简单,对于一个背包来说,我随便改变顺序,最后DP出来的结果是一样的
因此,我们可以把这个点当做最后一个加入,那么就很好删除了
显然可以扩展到多个点的情况
那么复杂度就是
O
(
n
m
)
O(nm)
O(nm)了
妙啊!
*1049: [HAOI2006]数字序列
首先,上升先减去位置左边变为不下降
然后第一问,显然就是
n
−
∣
最
长
不
下
降
子
序
列
∣
n-|最长不下降子序列|
n−∣最长不下降子序列∣
考虑第二问怎么做
先前后添加一个最小/最大
可以保证序列的最后一个是结尾
考虑DP
g
i
g_i
gi表示
i
i
i这个点结尾的答案
转移的话,就找到
f
i
=
f
j
+
1
f_i=f_{j}+1
fi=fj+1且
a
i
>
=
a
j
a_i>=a_j
ai>=aj的地方
然后考虑这一段怎么放
不难看出,这一段所有的数要么比
a
i
a_i
ai大,要么比
a
j
a_j
aj小
感受一下可以发现,一定是前后各一段,一段变为
a
i
a_i
ai,一段变为
a
j
a_j
aj
然后就可以得到一个
O
(
n
3
)
O(n^3)
O(n3)的做法
虽然数据是随机的。。然而期望还是
O
(
n
2
l
o
g
n
)
O(n^2logn)
O(n2logn)
看了下当年的做法,居然就是这么A的。。
然后翻了一下题解,发现还有优化空间
我们考虑,我们现在复杂度有一个问题在于我们去找分开两段的断点在哪里
这个是可以被优化的
具体来说,对于一段,我们先假设全部变为
a
i
a_i
ai,得出一个sum
那么最终的代价就是
s
u
m
−
(
y
−
x
)
∗
(
a
i
−
a
j
)
sum-(y-x)*(a_i-a_j)
sum−(y−x)∗(ai−aj)
x,y分别代表对于一个决策点,
[
j
,
k
]
[j,k]
[j,k]里面比
a
i
a_i
ai大的,
[
j
,
k
]
[j,k]
[j,k]里面比
a
j
a_j
aj小的
那么很明显,对于一个决策点k来说,
(
y
−
x
)
(y-x)
(y−x)就决定了他优不优秀
因此,我们可以在枚举
j
j
j的时候,维护一下
(
y
−
x
)
(y-x)
(y−x)的最大值和sum即可
哦,忘了说了,
(
y
−
x
)
(y-x)
(y−x)显然可以用一个前缀和的差来表示
因为不比
a
i
a_i
ai大的,那么就一定是比
a
j
a_j
aj小的了
因此,固定了
i
i
i之后,维护就很简单了
时间复杂度是
O
(
n
2
)
O(n^2)
O(n2)
3090: Coci2009 [podjela]
一开始以为直接贪心就好了。。
然后写了两行发现似乎不是很好贪
想了一下,发现直接DP就行了
f
i
,
j
f_{i,j}
fi,j表示
i
i
i的子树都解决了(不包括
i
i
i),只用了
j
j
j次,
i
i
i最大是多少
显然
j
j
j不会超过子树大小
那么就可以
O
(
n
2
)
O(n^2)
O(n2)DP啦
*4665: 小w的喜糖
做法大概有两种
首先,交换什么的变成重新分配就好了。。
可以先考虑
2
n
2^n
2n容斥,然后可以得到
(
−
1
)
∣
T
∣
(
n
−
∣
T
∣
)
Π
a
i
−
b
i
(-1)^{|T|}\frac{(n-|T|)}{\Pi{a_i-b_i}}
(−1)∣T∣Πai−bi(n−∣T∣)
DP即可
也可以直接DP
然后
f
i
,
j
f_{i,j}
fi,j表示前i个人,至少
j
j
j个人还是一样的有多少方案
一堆一堆糖果一起做,转移的时候,枚举一下当前这对糖果有多少个一样的
k
k
k
那么这个的方案数是
C
a
i
k
∗
C
a
i
k
∗
k
!
C_{a_i}^{k}*C_{a_i}^{k}*k!
Caik∗Caik∗k!
大概意思就是枚举怎么分配,后面那一块看做是
a
i
∗
(
a
i
−
1
)
∗
(
a
i
−
2
)
∗
.
.
.
∗
(
a
i
−
k
)
a_i*(a_i-1)*(a_i-2)*...*(a_i-k)
ai∗(ai−1)∗(ai−2)∗...∗(ai−k)就好了
最后没有填数的就全排列一下就行了
同样的,数字填进去有序,因此最后要除
Π
a
i
!
\Pi{a_i!}
Πai!
一开始想漏了些东西,面向样例得AC
**4380: [POI2015]Myjnie
不难想到DP
f
l
,
r
,
p
f_{l,r,p}
fl,r,p表示
l
l
l到
r
r
r的最小值为
p
p
p的答案是什么
然鹅想了很久不知道怎么转移
实际上可以枚举最小值在哪里来转移,那么就好做了
转移的时候要预处理一点东西,比较麻烦
感觉枚举最小值的位置比较巧妙
1226: [SDOI2009]学校食堂Dining
考虑到可以插队的人很少,考虑状压
f
i
,
j
,
k
f_{i,j,k}
fi,j,k到第
i
i
i个人,已知前面
i
−
1
i-1
i−1个人全部吃完,
i
i
i以及后面
7
7
7个人的状态,上一个吃的人距离
i
i
i差多远
暴力转移就可以了
因为以前A过一次就没写了,咕咕咕
4631: 踩气球
按题意模拟即可
3956: Count
冷静分析一下,发现好点对是
O
(
n
)
O(n)
O(n)级别的
把所有好点对找出来,然后随意维护一下就可以了
*3133: [Baltic2013]ballmachine
一开始理解错题了
可以发现,我们如果可以快速地找到当前是谁被添加/删除,复杂度就是对的
冷静分析一下,我们对于每一个节点距离一个值mn,表示子树里面最小的编号是什么
em…感觉这个模型还不错,记下来以后就不用想了
可以发现,我们把每一个儿子按mn排序,那么我们每一次选的就是一个dfs序最小的
想到这个就很好做了
因为要资瓷添加和删除,因此写一个set来维护当前可以到的点的dfs序的最小值
然后我们还要维护每个点最上面的祖先是谁
我们知道,dfs序互不相交,因此开个线段树维护一下就可以了
时间复杂度是
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
2298: [HAOI2011]problem a
冷静分析一下,发现每一个人的信息可以等价于,
[
l
,
r
]
[l,r]
[l,r]的人的分数是一样的
如果两个人的区间是相交的就冲突了
如果一个区间的人太多,也是冲突的
可以DP出最多有多少个人讲真话
简单DP就可以了
2466: [中山市选2009]树
f
i
,
j
,
k
f_{i,j,k}
fi,j,k表示第I个点亮不亮,有没有按
然后简单DP即可
*4662: Snow
先考虑
n
2
n^2
n2模拟
每一次挑一个最小的
然后会对某一个区间的人的
r
r
r取min,或
l
l
l取max
思考一下可以发现,整个过程可以用线段树来维护
*1560: [JSOI2009]火星藏宝图
没有想到这竟然是一个
O
(
n
m
)
O(nm)
O(nm)的DP233333
一直在想
m
2
m^2
m2的做法
发现不是很会。。
O
(
n
m
)
O(nm)
O(nm)的话,就是简单贪心一下就行了。。
以后看到这种题不要局限于
m
2
m^2
m2的思考啊
*1927: [Sdoi2010]星际竞速
em…下次见到这种DAG不相交路径反应要快点啊。。
和DAG覆盖类似
我们先假设所有点都用跳跃到达
然后对于每一条边,如果边权比跳跃还贵那么就丢掉
否则,就连上
跑费用流,每一次减去费用,直到费用为负就可以了
当然也有别的写法,S连向拆后的两个点,连向右部点的代价是跳跃的代价
然后原边加上,右部点连向T
全部流量都是1,也可以满足题目条件
**4663: Hack
并不会做这个
可以想到,我们的目标式把同一条路径上的边选两个变得没有用
尝试了几个奇奇怪怪的建图发现并没有什么用
思考了一下强连通缩点起来,然后得到一个DAG再做,但是似乎也没什么用
看了题解
把反向边建成
i
n
f
inf
inf就可以了,并不是很知道为什么这么搞QAQ
感受一下好像很对的样子,那就先记下来吧
以后简单同一条路径不可以割多个就要想起这个模型哇
3732: Network
最小生成树即可
3107: [cqoi2013]二进制a+b
细节比较多的模拟题。。没什么好说的
慢慢写就好了23333
可能一次写对还是挺困难的吧
一开始居然因为特判情况写错而WA。。
4205: 卡牌配对
挺好做的题。。提示就是叫你写网络流的2333
然后你n^2建边肯定是不行的
对于不互质的那两个,显然可以通过质因数连起来
一开始看错了,一位要恰好有一个,然后发现这个第三个十分棘手
又看了一次题,发现是至多。。
那就好搞了啊,直接不管第三个是个啥就完事了
容易发现每个数的质因数不超过个不一样的
因此每个点连出
3
∗
3
∗
3
=
27
3*3*3=27
3∗3∗3=27条边
图就很小了,可以通过
3343: 教主的魔法
居然一时没有想起来分块23333
因为Q很小,因此也可以用线段树来维护这个东西
卡了一会空间才过
1787: [Ahoi2008]Meet 紧急集合
显然可以动态点分治
但是并没有这个必要。。
答案一定是在某两个点的LCA处
具体来说,如果三个LCA都一样,那么就取这个LCA
否则会有两个一样的,去不一样的那个就行了
正确性显然
1202: [HNOI2005]狡猾的商人
很经典的题
差分变为前缀和,然后维护一个带权并查集即可
3810: [Coci2015]Stanovi
f
i
,
j
,
a
,
b
f_{i,j,a,b}
fi,j,a,b表示当前的矩形为
i
∗
j
i*j
i∗j,横着有
a
a
a个墙,竖着有
b
b
b个墙的答案
简单DP就可以了
3957: [WF2011]To Add or to Multiply
可以发现,假设输进去的是x,最后的答案可以写成
x
∗
m
k
+
b
1
∗
a
k
+
b
2
∗
m
k
−
1
+
b
3
∗
m
k
−
2
+
.
.
.
+
b
n
∗
m
0
x*m^k+b_1*a^k+b_2*m^{k-1}+b_3*m^{k-2}+...+b_n*m^0
x∗mk+b1∗ak+b2∗mk−1+b3∗mk−2+...+bn∗m0
可以发现,
k
k
k不会超过30
于是暴力枚举
k
k
k,就可以把
x
∗
m
k
x*m^k
x∗mk丢掉了
那么也就是构造后面那一坨东西,使得他在
[
L
,
R
]
[L,R]
[L,R]之间
简单贪心即可
**4069: [Apio2015]巴厘岛的雕塑
感觉很妙
一位一位固定,每一位看看是否可以填0
但是我们怎么知道是否可以满足前面的条件呢?
DP!
转移的条件就是
(((x>>(d+1))|ans)==ans)&(!(x&(1LL<<d)))
在这种一位一位固定的题里面,尝试一下这种DP也不错啊
3681: Arietta
写个线段树优化一下建图
没了
3727: PA2014 Final Zadanie
先考虑这么一个式子
b
x
=
b
f
a
−
c
[
x
]
+
s
u
m
−
c
[
x
]
b_x=b_{fa}-c[x]+sum-c[x]
bx=bfa−c[x]+sum−c[x]
其中
c
c
c为
x
x
x这个子树
a
a
a的和
s
u
m
sum
sum是整一个子树
a
a
a的和
可以发现,如果我们知道了
s
u
m
sum
sum,那么所有的
c
c
c都可以求出来
那么问题就是怎么把
s
u
m
sum
sum弄出来
猜想可以二分答案
那么如果写一个好的check就很关键了
不难发现,有一个东西
c
c
c是这个式子求不出来的,那就是
r
t
rt
rt
但是我们可以发现,
b
′
[
r
t
]
=
∑
i
=
2
n
c
[
i
]
b'[rt]=\sum_{i=2}^nc[i]
b′[rt]=∑i=2nc[i]
可以发现,如果
b
′
[
r
t
]
=
b
[
r
t
]
b'[rt]=b[rt]
b′[rt]=b[rt]那么就是合法的
再观察一下,每一个
c
c
c,随着
s
u
m
sum
sum变大而变大
也就是说,如果
b
′
[
r
t
]
>
b
[
r
t
]
b'[rt]>b[rt]
b′[rt]>b[rt],那么我们二分的
s
u
m
sum
sum就大了
否则就小了
但是这样又一个log,过不去
进一步我们可以发现,其实我们可以直接把
s
u
m
sum
sum算出来,因为
s
u
m
sum
sum每一次增大
2
2
2,都会使得
b
′
[
r
t
]
b'[rt]
b′[rt]增大
(
n
−
1
)
(n-1)
(n−1)
因此,两次dfs即可
**4699: 树上的最短路
一个比较显然的做法,是建立两颗线段树
然后线段树优化建图来跑SPFA
但是这样边数已经是
m
l
o
g
2
n
mlog^2n
mlog2n了,并不是一个优秀的做法
看到讨论Claris说有更优秀的做法
想了一下,打算魔改dij
先分析一下一个坍塌只有第一次用的时候才是有效的
dij的时候,把边和点全部丢进去
边的代价是第一次到达的点+边权就可以了
找点可以用并查集压缩一下
那么问题就在于,怎么找经过一个点所有的坍塌,并删除它
然后因为这个不是核心类容看了题解QAQ,因为我一想吧所有坍塌丢到线段树上,那么复杂度就变回两个log了2333
我也太傻逼了吧
实际上,对于一个坍塌,如果他经过一个点x的话
一定满足它的起点在
x
x
x的子树里面,终点在外面
用线段树维护一个dfs一个区间里面,终点dfs序的最大最小值就可以了
然后每个节点维护一个堆,删除的时候换人就可以了
这样做就是漂亮的一个log了
当然L1,R1谁做起点,谁做终点是可以反过来的
em…如果思考再深入一下这题就不需要看题解了啊
真是可惜了。。
似乎成为托更大王了
但是。。我似乎确实没有做什么题啊23333
那么就祝大家新年快乐吧。
4527: K-D-Sequence
em…一直想的是美枚举最小值位置来做
想了半天只会
l
o
g
2
log^2
log2的
然后听说都是log的233
考虑枚举右端点,发现可以用线段树维护,就没什么了
**5317: [Jsoi2018]部落战争
可以发现,只有凸包上的点是有用的
问题等同于
A
+
d
=
B
A+d=B
A+d=B
给定A,B集合,对于一个d问存不存在
移项
d
=
B
−
A
d=B-A
d=B−A
合并出后面的凸包,这个有一个新姿势
还有就是合并的时候记得多加一个点,否则会错2333
那么问题就是判断给定点在不在凸包里面了
用二分+叉积来实现即可
1221: [HNOI2001] 软件开发
费用流一下就可以了
**2753: [SCOI2012]滑雪与时间胶囊
一开始乱搞,发现怎么都不行
其实正解很简单,先按终点的高度排序,再做K…
思考一下觉得很对
似乎有一段时间没有更新了
em…定下一个新计划把
开发一下45版的题
然而似乎很多都没有题解
那我就尽量写一写吧。。em…虽然感觉网上直接查还是查不到
**5440: 老虎机
可以发现
最多只会在两台机操作
一台机的直接判掉
枚举第一台是哪一个,每出一个球,他对应的答案就是加上其他的包含这个球的颜色种类数
那么显然是按这个从大到小出求
记录一下对于每一个颜色的最大最小值就可以了
**5401: s
并不会做这个。。
看题解吧
5439: 字符串
可以发现,长度不超过8,于是可以爆搜每个串,然后
O
(
n
)
O(n)
O(n)判断
因为,你只选一个字符都可以达到
n
2
/
9
n^2/9
n2/9的级别
但是这样状态太多了,接近1W个,考虑优化
假设出现次数最多的字符出现了
n
/
w
n/w
n/w次
那么他的答案就是
n
2
/
w
2
n^2/w^2
n2/w2
考虑如果长度超过7,那么至少有一个数出现3次
n
2
/
m
n^2/m
n2/m的另外一个意义是
n
∗
出
现
次
数
n*出现次数
n∗出现次数
那么显然,出现次数不超过
n
/
w
/
3
n/w/3
n/w/3
然而
w
w
w一定不小于
3
3
3
因此肯定不优,于是长度到6就OK了
进一步的,如果有一个字符出现超过3次就肯定不优
状态数大概有
270
270
270种
如果把有循环的减掉就是
255
255
255种
判断的
O
(
n
)
O(n)
O(n)很不满,所以跑得飞快
**3744: Gty的妹子序列
乱入一个题
带log的很简单
然而不会不带的。。
上网看题解吧。。感觉还是挺妙的
5450: 轰炸
又乱入一个
缩点之后简单DP就可以了
似乎答案等价于最长路?