杂题选刷

[TOC]

杂题选刷

记录一下自己最近做的题吧

P6619 冰火战士

树状数组+二分/线段树

P6619 [省选联考 2020 A/B 卷] 冰火战士

  • 10pts10pts

不离散化,直接暴力

  • 20pts20pts

最优解一定在某个战士的温度值取到。

这就是考场上导致我没有想出60pts60pts的原因(第二个就是没注意到2操作也要输出答案,浪费11个小时debugdebug

暴力枚举温度,暴力更新即可

复杂度:O(Q2)O(Q^2),期望得分:20pts20pts

  • 60pts60pts

树状数组+二分

还是先可以离散化一下温度,设I[t]I[t]为在tt温度下冰战士的能量和,F[t]F[t]是火战士的能量和,答案就是2min(I(t),F(t))2\cdot\min(I(t),F(t))

则显然有I(t)I(t)单调不降F(t)F(t)单调不增

我们可以二分一个I(t)I(t)F(t)F(t)最接近的合适的温度,分别用两个树状数组维护冰和火战士(一个前缀和,一个后缀和)

复杂度为O(Qlog2Q)O(Q*log^2Q),期望得分:60pts60pts

  • 100pts100pts

现在还不会,以后更新

代码见P6619 [省选联考 2020 A/B 卷] 冰火战士

P4062 Yazid 的新生舞会

思路题+线段树/树状数组

淦,我之前写的东西没保存

P4062 Yazid 的新生舞会

给定一长度为nn的序列,求有多少子序列[l,r][l,r]的众数出现rl+12\frac{r-l+1}{2}

  • 算法一(针对n300n\leq 300

考虑枚举所有区间,然后求其众数及出现次数,并判断是否超过区间总长的一半,统计答案即可。时间复杂度O(n3)O\left( n^3\right)

  • 算法二(n2,000n\leq 2,000

考虑先枚举区间的左端点ll,再从左到右枚举右端点rr并用数组维护每个数的出现次数,同时使用变量维护当前众数、众数的出现次数。不难发现,当右端点向右移动时,这些信息都是非常方便维护的。于是我们便可以在O(n2)O\left( n^2\right)的时间复杂度内统计所有答案。

  • 算法三(type=1type=1

对于0101序列,我们不难发现,众数出现次数严格大于子区间长度当且仅当子区间内0,10,1出现次数不同(那么那个出现次数较多的就是众数)。于是我们将原序列中的00视作1-1,并对该序列求前缀和SS,则子区间[l,r][l,r]为“新生舞会的”,当且仅当SrSl1=0S_r-S_{l-1}\not= 0

有了这个性质我们就可以O(1)O(1)来求解子区间[l,r][l,r]是不是符合要求了,但是不幸的是这样仍需要枚举l,rl,r,复杂度仍是O(n2)O(n^2)

我们不妨反着来想,子区间[l,r][l,r]不是“新生舞会的”,当且仅当SrSl1=0S_r-S_{l-1}=0Sr=Sl1S_r=S_{l-1}因此对SS进行排序并从小到大统计相等的个数然后用总的子区间数量n(n+1)2\frac{n\cdot(n+1)}{2}减去相等的个数即为答案

  • 算法四(type=2type=2

对于所有数的出现次数都较小(不超过1515)的情况,不难发现所有“新生舞会的区间”的长度也会较小(不超过2×151=292\times 15-1=29)。于是使用算法二,枚举所有长度少于3030的区间并统计答案即可。

  • 算法五(type=3type=3

对于Ai7A_i\leq 7的测试点,我们不妨枚举所有值作为众数的情况。考虑统计所有众数为kk的“新生舞会的”区间,将所有等于kk的位置取为11,不等于kk的位置取为1-1,得到新序列BB并求前缀和得到序列SS,则区间[l,r][l,r]需要被统计,当且仅当SrSl11S_r-S_{l-1}\geq 1。从左到右枚举右端点,并用线段树维护当前右端点左边每种前缀和出现的次数即可。时间复杂度O(8nlogn)O\left( 8nlogn\right)

  • 算法六(100pts100pts

考虑改进算法五。我们考虑取出所有BB中的极长1-1子区间,观察这些区间中的所有点作为右端点对答案的贡献。不难发现极长1-1子区间[l,r][l,r]中的所有点作为右端点对答案的贡献为i=1rl+1j=Sl1i1cnt[j]\sum_{i=1}^{r-l+1}\sum_{j=-\infty}^{S_{l-1}-i-1}cnt[j],其中cnt[j]cnt[j]表示在区间[0,l1][0,l-1]之间前缀和为jj的端点数目;在统计这段区间的答案后,我们还需要对区间[Si1(rl+1),Si11][S_{i-1}-(r-l+1),S_{i-1}-1]中的所有cntcnt均进行+1+1操作。显然地,我们使用一个维护BiB_iCi=i×BiC_i=i\times B_i的线段树就可以支持这些查询、修改操作。于是我们使用这棵线段树维护相关信息,并从左到右枚举右端点,统计答案即可。

不难发现,极长1-1子区间的数目与序列中kk的数目同阶,因此,对于统计众数为kk的“新生舞会的”区间的时间开销,不难发现我们通过上述优化将时间开销缩短到了O(Aklogn)O\left( 序列A中k的数目\log{n}\right)

于是,总时间复杂度即为O(kAklogn)O\left(\sum_{k} 序列A中k的数目\log{n}\right),即O(nlogn)O\left(n\log{n}\right)

51Nod 1327 棋盘游戏

区间dp

1327 棋盘游戏

给定nmn\cdot m的方阵,每个格子可以填11或者00,求每一列最多只有1111,第ii行从左开始向右连续left[i]left[i]个格子只有1111,从右边开始向左连续right[i]right[i]个格子只有1111的方案数

读完题感觉有点像CSPday2CSPday2的题,怪

有一种浓浓的区间dpdp的味道,这道题的显然不能按照行来做(行的限制比较多,很难搞),所以我们应该按照列来定义状态f[i][j][k][0/1]f[i][j][k][0/1]为到第ii列,左边的列填了ii11,右边的列填了jj11,当前列有没有11,这样转移不了啊

我们可以思考每一列可以放的情况:如果一些行的左区间的终点在该列,那么这些行是必然要被放的(不然就不符合要求了),如果一些行的右区间从这一列开始,那么没有处理完的行就会多出几个,放到后面的状态处理即可,还有一种情况就是选择leftleftrightright之间的部分放一个11

如下图(ps:图画的不太对,蓝线应该在格子里,自己YYYY吧,我懒得改了)所示,在蓝色线那一列,第11,22,44,66的红色必定已经填过了,而且黄色的第1,21,2行可以填了,第4,64,6行就是可以选择leftleftrightright之间的部分放一个11的情况

示例-1

那么状态就可以定义了f[i][j][k]f[i][j][k]表示到了第ii列,在这之前有jj没有放过妻子,且已经有kk行到了有区间(黄色部分)

li,ri,midil_i,r_i,mid_i分别表示第ii行左区间右端点为ii,右区间左端点为rir_i,第ii列没有覆盖住的行数

根据上面的分析:每一列的转移要添加ri+1r_{i+1}的右区间放置机会,要将l[i+1]l[i+1]全部搞定。
则转移为:

  • 放在红色格子

f[i+1][j+1li+1][k+ri+1]+=f[i][j][k]Aj+1li+1f[i+1]\left[j+1-l_{i+1}\right]\left[k+r_{i+1}\right]+=f[i][j][k] * A_{j+1}^{l_{i}+1}

  • 放在黄色格子

f[i+1][jli+1][k+ri+11]+=f[i][j][k]Ajlj+1(k+ri+1)f[i+1]\left[j-l_{i+1}\right]\left[k+r_{i+1}-1\right]+=f[i][j][k] * A_{j}^{l_{j+1}} *\left(k+r_{i+1}\right)

  • 放在白格子

f[i+1][jli+1][k+ri+1]+=f[i][j][k]Ajli+1midi+1f[i+1]\left[j-l_{i+1}\right]\left[k+r_{i+1}\right]+=f[i][j][k] * A_{j}^{l_{i+1}} * m i d_{i+1}

51Nod 1683 最短路

1683 最短路

随机0101矩阵,对每个kk(1,1)(n,m)(1,1)\sim(n,m)最短路为kk的概率,路径长度指的是不能向左走前提下路径上权值为11的格子个数。n6,m100n\leq6,m\leq100

一个显然的性质:相邻两格子最短路值相差不超过11

剩下的我不会了......以后再做吧

51Nod 1843 排列合并机

1843 排列合并机

看不懂题,弄不懂样例,告辞

老师给安排的题目也太难了吧,我都不会(自闭ing

P5970 Nim z utrudnieniem

博弈论+dp

Nim z utrudnieniem

AABB在进行NimNim博弈,AA是先手,但是BB在开始之前可以扔掉dd的倍数堆的石子(不能扔掉全部的),问BB有多少种扔的办法使BB必胜。

显然BB必胜的条件为a1a2an=0a_1 \oplus a_2 \oplus \cdots a_n = 0(NIMNIM博弈的结论)

显然可以这么来定义状态f[i][j][k]f[i][j][k]表示前ii堆石子,扔掉了jj堆(在mod dmod\ d下),异或和是kk的方案数

f[i][j][k]=f[i1][j][k]+f[i1][j1][kai]f[i][j][k]=f[i-1][j][k]+f[i-1][j-1][k\oplus a_i]

复杂度为O(ndmaxai)O(n\cdot d\cdot maxa_i)

现在的问题在于怎么把maxaimaxa_i这一项变小?

有一个神奇的结论

因为对于任意一个正整数NN,它和比它自己小的数字异或起来的结果不会超过N×2N \times 2

所以只需要把aia_i从小到大排序,这样复杂度就变成O(md)O(m\cdot d)

现在问题在于空间开销太大了。

显然可以用滚动数组,但是仍然太大,因为我们必须要把ii这一维给省掉。

只需要在每一层ii时,按照kk从大到小的顺序进行转移即可。

还要注意nndd的倍数时,会算上全选的情况,答案需要减去11

代码见P5970 Nim z utrudnieniem 题解

P4042 [AHOI2014/JSOI2014]骑士游戏

有后效性的dp

$$\large\text{要用魔法打败魔法}$$

P4042

一共有nn种不同的怪物,每种怪物都可以用两种方式杀死,第一种消耗sis_i体力将怪物变成另外一种或多种怪物,第二种消耗kik_i体力,可以直接杀死,问最少消耗体力杀死11号怪物

读完题之后感觉是个图的模型,但是建了一下图发现不太好建边,更不太好跑最短路。(淦

那就从dpdp角度来思考一下。

f[i]f[i]杀死第ii号怪需要的最小体力,显然有f[i]=min(ki,si+j=1Rif[ri,j])f[i]=\min(k_i,s_i+\sum\limits_{j=1}^{R_i}f[r_{i,j}])ri,jr_{i,j}表示用蛮力杀死ii后分裂的第jj个。

经过了上面的建图过程就会发现,可能会存在环(也就是有后效性),到时候就死了。(淦×2\times2

现在大概只能在dpdp的式子上下手了,显然后效性在dpdp式子后面的一项上。

当且仅当f[ri,j]<f[i]\forall f[r_{i,j}]<f[i]f[i]f[i]才能被后面一项更新,我们不妨换一个角度来进行转移,用某一个ff值去更新其他的ff

一个更显然的性质,对于kik_i最小的怪物,f[i]=kif[i]=k_i,所以我们对ff建立一个堆,然后每次弹出一个点ii来更新其他的fri,jf_{r_{i,j}},如果更新完了,则就把fri,jf_{r_{i,j}}放到堆里(这样就确保了不会有后效性)

代码见骑士游戏

P3592 [POI2015]MYJ

区间dp

P3592

nn家洗车店从左往右排成一排,每家店都有一个正整数价格p[i]p[i]。有mm个人要来消费,第ii个人会驶过第a[i]a[i]个开始一直到第b[i]b[i]个洗车店,且会选择这些店中最便宜的一个进行一次消费。但是如果这个最便宜的价格大于c[i]c[i],那么这个人就不洗车了。请给每家店指定一个价格,使得所有人花的钱的总和最大。

因为每个人不洗车的当且仅当[li,ri][l_i,r_i]中最小的p[i]>c[i]p[i]>c[i],所以有个显然的性质:每个商家价格是c[i]c[i]一定是最优解之一。因此我们可以将c[i]c[i]离散化。

f[l][r][i]f[l][r][i]表示区间[l,r][l,r]内最小值是ii,从满足labrl\le a \le b\le r的人中获得的最大收益

枚举区间最小值所在的点kk,则满足lakl\le a\le kkbrk \le b\le r的点最小位置就是kk,统计出cic\ge i的人有几个

f[l][r][i]=maxlkr{realci×cnt+maxhif[l][k1][h]+maxhif[k+1][r][h]}f[l][r][i]=\max\limits_{l\le k\le r}\{realc_i\times cnt+\max\limits_{h\ge i}f[l][k-1][h]+\max\limits_{h\ge i}f[k+1][r][h]\}

代码见P3592 [POI2015]MYJ

CF319E Ping-Pong

并查集+线段树

CF319E Ping-Pong

规定区间(a,b)(a,b)到区间(c,d)(c,d)有边当且仅当c<a<dc<a<dc<b<dc<b<d

起初区间集合为空。有nnn105n\leq 10^5)次操作,每次操作形如:

  • 1 x y(x,y109|x|,|y|\leq10^9):加入一个新区间(x,y)(x,y),保证新区间长度最长
  • 2 x y:询问第ii个加入第区间能否到达第jj个加入第区间,保证询问合法

连边的两种情况:第一种是包含,小的向大的连边;第二种是相交不包含,连双向边。

注意到答案最后不会走超过11条单向边

所以可以用并查集维护,用线段树拆分区间,然后连边

P4132 [BJOI2012]算不出的等式

思路题

P4132 [BJOI2012]算不出的等式

给定奇质数p,qp,q,求k=1p12kqp+k=1q12[kpq]\sum\limits_{k=1}^{\frac{p-1}{2}}\left\lfloor\frac{k q}{p}\right\rfloor+\sum\limits_{k=1}^{\frac{q-1}{2}}\left[\frac{k p}{q}\right]

读完题之后,看不懂这个式子是求了个什么东西,算了,还是打表看题解

这么恶心人的式子竟然就是求直线下方点的个数,我佛了

该式两部分分别是一个(p12,q12)(\frac{p-1}{2},\frac{q-1}{2})方格图主对角线分成的两部分的整点