9月做题记录

9月做题记录

✩ trick
✯ 会大部分,要tj提示
✬ 会小部分/完全没想到,看了tj才会
◈ 脑电波
✡ 有某一算法的神秘通用性质
⊗ 待补

ARC146C

显然只要所有大小为奇数的子集的异或和都互不相同即可

那么dp[i]表示长度为i的答案,考虑加入一个新的数a,那么a只需要不与所有大小为奇数的子集的异或和相同即可,而又因为原本的那些就已经互不相同了,所以dp[i+1]=dp[i]×(2N2i1)

然后注意这样求出的dp[i]是有序集合,那么真正的答案就是dp[i]i!

这种求2-sat字典序最小解的做法按理来说是O(NM)的,但是似乎并卡不满啥的,总之能过

ARC146D

  • 做法1

限制转换为APiXi当且仅当AQiYiAPiXi当且仅当AQiYi

这样就可以2sat了,然后尽量让每个A取到最小即可

  • 做法2 ✯

是官方tj的做法

把限制转换为APiXi当且仅当AQiYiAPi<Xi当且仅当AQi<Yi

然后先把所有值都赋为1,然后一步步的调整即可

复杂度O(N+K)

CF1994G

Hint真的蚌埠住:

  • Think of the most stupid solution you can do
  • Do memorization and some cuts
  • Done!

考虑x在第i位取0/1,会导致贡献2i×(ki/nki),其中ki表示这n个数中第i位为1的数的数量

发现这样小的位会影响到大的位,但大的位不会影响小的位,所以 the most stupid solution就是从到大递归,设状态(i,sum)表示后i位的贡献和除以2i的值

然后发现,因为sumn,所以总的状态数就只有O(NK)的,所以就可以过了

P3599 Koishi Loves Construction

感觉除了打表找规律找出正解来,很难单独凭人类智慧直接推测出来啊

  • X=1的情况

此时即要求不存在区间[l,r](l>1)使得区间和同余0,那么一定有a1=n

如果n为大于1的奇数,此时有1+2+...+n10modn,即不合法

所以n只能为1或偶数

打表找规律可得:ai=[i%2==0]i1/[i%2==1]n+1i

此时对于ai序列在模n下等价于{0,1,2,3,4...},那么sumi={0,1,1,2,2...}显然合法

  • X=2的情况

此时要求不存在区间[l,r](l>1)使得区间积同余1且不存在pordi0(i<n),那么一定有an=na1=1,可以发现,如果n不是质数/1/4,那么一定能用<n的不同数拼出n,即prodi0(i<n)一定会成立

所以n一定是质数或14

n=1/4特判一下

通过打表找规律又可得:prediimodn,那么aiii1modn,如果ai=aj即有ii1jj1modn,化简得到ij显然在ij时不成立

AGC030C

K500,那么直接让n=K,然后第i层全部等于i即可

否则当K>500时,发现同一行全部相等的模型不适用了,因为如果替换第i行中的任意一个,都会导致与这一个相邻的两个i与其他的i的数量不同

考虑变成斜着的形式

123456
234561
345612
456123
561234
612345

发现这样构造后,相同的数之间就互不影响了,那么这时加入一个新的数7进来,只需要任意替换掉某一个数的一半为6,且替换掉的位置不是在斜线上相邻的即可

eg:

123456
274561
345612
456127
561234
612745

这样最多能塞2N个数,发现K的最大值刚好是2×500,那么这样构造就是合法的

AGC035C

ii+n间的路径的异或和为i,即ii+n之间的点(不包括ii+n)的异或和为i

首先,如果lowbit(n)=n,那么一定无解,因为不可能找出数来凑出n

然后发现有个很好的性质,如果i是偶数,那么i xor1=i+1,那么此时可以连边(i,1)(i+1,1)(i+n,i+1)(i+1+n,i)

如果n是奇数,现在就只剩下1+n没连了,此时随意找一个偶数i,连边(1+n,i+n/i+1+n)即可

如果n是偶数,1+n还是按照这种方式连,此时还有nn+n没连,考虑用lowbit(n)nlowbit(n)来凑出n,期望是构成路径nlowbit(n)nlowbit(n)n+n,但是显然lowbit(n)要到nlowbit(n)必定经过一个1,那么也就是说,实际的路径是nlowbit(n)→→nlowbit(n)n+n,发现任意两个<n间的点间,1是不可避免的,那么换个思路,把nlowbit(n)nlowbit(n)n+n中的lowbit(n)替换成lowbit(n) xor11,那么路径就变成了nlowbit(n) xor11nlowbit(n)n+n,即连边(n,lowbit(n) xor1)(nlowbit(n),n+n)即可

复杂度O(N)

AT_hitachi2020_e Odd Sum Rectangles

非常牛的题

要求尽量多的矩阵内的数之和为奇数,因为只在意奇偶性,那么换成异或和

不失一般性的假设NM

先求出sum[i][j]表示矩阵(1,1,i,j)的异或和,那么矩阵(a,b,x,y)的异或和即为sum[x][y] xor sum[a1][y] xor sum[x][b1] xor sum[a1][b1],那么对于sum[i][j]2n×2m的矩阵(包含i=0/j=0),即要求这个矩阵的四个角的异或和为1a<xb<y

考虑先确定ax即先确定行,一共有C2N2行,再来考虑选的列by,因为要求四个角的异或和为1,所以我们把所有列分成两类,一类是对应列中a行和b行值不同的,有k个,另一类是值相同的,有2Mk个,那么显然,合法的矩阵的两个列必须是不同类型的列,所以列的方案数总共就是k(2Mk)22M2,当且仅当k=2Mk时等号成立,也就意味着,答案的上界在每两行间,对应的值不同的列的数量恰好为2M1时取到

考虑构造这个上界对应的sum[i][j]sum[0][j]sum[i][0]都是0,其余的,满足每两行间对应的值不同的列数恰好为2M1

因为已经sum[0][j]的值,且总的行数是2M的,所以考虑倍增构造

如果已经知道02i1的构造方法,考虑构造2i2i+11,先把02i1copy2i2i+11,当然直接copy过后肯定不合法,此时再给2i2i+11中含有2i的列的值异或上1,就可以了

证明:

  • 对于x[0,2i1]y[0,2i1],因为已经是合法构造了,且后面的操作没有再改变它们,所以第x行和第y行是合法的
  • 对于x[2i,2i+11]y[2i,2i+11],因为x2iy2i是合法的,且它们分别取自x2iy2i,虽然有变换,但是xy变换的列是相同的,所以合法
  • 对于x[2i,2i+11]y[0,2i1]x2iy是合法的,而x是在x2i的基础上改变了有2i的列

考虑研究任意两行ab的差别,考虑从第一个2i+11a,bi开始回溯操作,如果当前回溯中,ab都在被新加入的那一侧,那么它们的差别等价于a2ib2i的差别,那么现在考虑在2j+11a,bj,此时不失一般性的假设a是已经有的一侧,b在新加入的一侧,那么ab的变化就是ab2j的差别,再算上那些含2j的列,那么总结下来,任意两行ab的差别可以用一个集合S表示(Sg中存的二进制的位),如果当前列kS中的奇数个元素,那么ab这一位不同

因为可以知道,二进制中所有位是独立的,所以ab当前列不同的概率就是12,那么也就是刚好一半的列不同,复合我们的限制

再回到原问题,现在知道了x2iy的差别集合S,那么在x2i的基础上变化了含有2i的列后,因为二进制中所有位独立,所以会有12原本x2iy不同的列改变,此时变成了相同的,有12原本x2iy相同的列被改变,此时变成了不同的,那么总共xy依旧还是有一半的列不同,此时xy的差别集合就是S{i}

复杂度O(2N+M)

CF1267H Help BerLine

首先,可以通过惊人的注意力注意到log328500=23,不过这只是后面要用到的方案的一步证明,所以感觉就算注意到了就没啥p用,况且除了bot真有人类能注意到吗

总之这个24是一个log级别的东西,所以考虑缩小问题规模,也就是考虑递归子问题

先考虑只染一种颜色,那么一定有任意时刻这种颜色的点都不能相邻,发现如果把染了这种颜色的点去掉后,把其他点单独提出来,变成一个新的序列,如果这个序列也是合法的,那么加上原本那些染了色的点进去依旧合法

那么考虑怎么染色,肯定想尽量多的染色,有一个比较朴素的想法,让操作从后往前,每次考虑当前操作的点有没有被标记,如果没有,给它染色并标记当前与它相邻的点

发现这样至少可以染n3个点,即剩下23n个点,那么也就意味着需要有n×23K<1,也就是说颜色数量K至少是log328500级别的

那么就这样一直递归子问题即可

复杂度O(NKlogN)

CF1270E ✯✩

在网格图上无敌的黑白染色...!

真没想到这也能染,太牛了

  • 第一种是纯粹的黑白染色

首先根据一个点(x,y)x+y的奇偶性把点染成黑白两色,然后如果两种颜色的点都存在,那么可以就这样分配

否则如果只存在x+y为偶数的点,那么把点变成(x+y2,xy2),可以证明两点间的距离变成了原来的12倍,好像说这是啥旋转,感觉像是顺时针转了135度然后顺带压缩了一下

如果是奇数,可平移一位

那么一直转,直到出现不同色的点为止,然后可以发现,因为每次任意两点间距离会变成原来的12倍,而一个原本不是原点永远不会变成原点,所以旋转次数是O(logV2)的,也就是O(logV)

  • 另一种做法,就是直接分别考虑xy的奇偶性,然后分成四类,然后大力分讨即可,感觉没上种方便(

ARC148D mod M Game

考虑最后只剩两个点xy没被选择时,设Alice取的数之和为ABob的为B,那么必须满足A+xB+y以及A+yB+x,那么一定有2x2y,e那么有xyxy+m2m是偶数)

考虑xyxy匹配,xy+m2m是偶数)的xy匹配,那么如果最后所有点都匹配上了且匹配的xy+m2是偶数对,那么Bob显然必胜

如果有点没匹配上,那么显然Alice可以通过操作使得不匹配点的最后一步不满足2x2y,那么Alice必胜

P4484 [BJWC2018] 最长上升子序列

首先肯定不能是逐个在序列的末尾添加数的这种求法,显然状态数爆表

考虑从小到大的添加数字,如果把当前数放到ii+1之间,设dp[i]表示以i为结尾的最长上升子序列,那么dp[j]=dp[j1]j>i+1dp[j]=dp[j]jidp[j]=k[1,i]dp[k]+1j=i+1,那么考虑记前缀最大值数组f[i],发现f[i1]f[i]f[i1]+1,所以改为记录差分数组g[i]表示f[i]f[i1],那么这个g[i]就是一个01数组,而每次插入到ii+1之间的话,就是插入一个1ii+1之间,然后原本的i+1后面的第一个1变成0

复杂度O(2NN2),但肯定跑不满的,但依旧不太能过,所以需要打个表(

P6970 [NEERC2016] Game on Graph

称希望平局的是0,不希望平局的是1

给每个点两个状态,一个是0先手,一个是1先手,那么显然,如果有边(x,y),那么会有(x0,y1)(x1,y0),即把一个点拆成两个,分别表示两个状态

然后先考虑判能否平局,有两种方式

  • 判平局

先缩点,变成DAG图,然后考虑最底层的点,如果是一个size2的点,那么这个点中的所有点都是平局,然后考虑往上推,如果一个0点存在出边指向一个平局状态的点,a那么这个0点为平局状态,如果一个1点所有指向的点均为平局状态点,那么这个1点是平局状态

除此之外,还有一些比较复杂的情况,比如偶环之类的,总之要大力分讨一下

然后就可以这样一直类似染色的方式染上去即可,然后对于不是平局的点,就普通的博弈做法即可

  • 判不平局

这种做法要好写一些

对于一个出度为0的点,其是不平局的,然后给它标记上,那么对于一个0点,如果它所有的出边都指向非平局点,那么它是平局点,如果一个1点存在非平局点的出边,那么就是非平局点

这个也是类似染色的就染上去就行了,判断具体是谁胜依旧普通的博弈做法

luogu的第一篇题解的写法比较妙,如果是比较普通的写法的话,注意不能标记和胜负同时标记,因为这样无法保证x一定比x的某个出边更早加入队列中

复杂度O(N)

AGC002E Candy Piles ✯✩

每次要么全部1,要么删最大的,可以发现,只要当前最大的不被删,那么一直都是最大的

考虑网格图,将ai从大到小排序,然后放网格图上,全部1就是向上走一步,删最大就是向右走一步,边界上是必输,那么就推回来其他点的状态

发现斜线上的点的状态相同,那么求出原点斜出去接近边界的那个点的状态即可

复杂度O(NlogN),瓶颈在排序

CF1411F/CF1464D The Thorny Path

可恶喵!导数还在追我!

显然答案为sziszi为第i个置换环的大小

通过打表可以发现,最优的情况是尽量使得分到的每一个sz都为3,具体的,有:

  • n%3==0szi=3
  • n%3==1,要么有两个szi=2,其余为3,要么有一个szi=4,其余为3
  • n%3==2,只有一个szi2,其余为3

具体证明:

显然szi=2/4都是不得已的折中策略,那么只需证明szi=3是最优策略即可

由高维不等式ai(aim)m可知,当ai尽量平均时能取最值,设这个平均的值为x,即x=ai=nm,设ai=n

那么有求f(x)=xnx的最大值,考虑它的单调性,因为n是常数,无影响,去掉,现在来考虑g(x)=x1x的单调性

g(x)=x1x=elnxxg(x)=elnxx1lnxx2

显然x=e时取得最大值,但又要求x是整数,所以考虑g(2)g(3)的大小,发现g(3)>g(2),所以x3时最优

那么显然一个环i能一次操作拆分成aszia两个部分,而两个环ij能一次操作合并成szi+szj的大环

对于n%3==0的情况,只需要先将所有szi>3的部分拆了,然后现在剩下了一下szi=1szi=2的部分,优先12匹配,剩下的再随便弄一下就行

对于n%3==1的情况,如果是有两个szi=2的情况,先拆szi>3的部分,然后先用剩下的szi=1/2的拼出两个2,然后再去凑3即可;如果是一个szi=4的情况,可以先去枚举是那个环拆出4的部分,然后剩下的就用n%3==0的做法去做即可

对于n%3==2的情况,依旧先拆所有szi>3的部分,然后先用剩下的szi=1/2的拼出一个2,然后再去凑3即可

ARC180E LIS and Inversion ✯✩

这种题一般都是先从代价/价值最小/最大一点点转移到其他情况

首先考虑要求代价为0的最长序列,那么直接设计dp状态,dp[i][j]表示前i个数中,以前i个中第j小为结尾的最长序列长度

那么有转移:

dp[i][j]={dp[i1][j1]maxk=1j1dp[i1][k]+1(jiai)

f[i][j]=maxk=1jdp[i][k],则转移变成:

f[i][j]=max(f[i][j1],f[i1][j1]+[jiai])

显然有f[i][j]f[i][j1]+1,直接交换dp[i][j]的序列中的jj1即可得证

那么现在找出差分数组g[i][j]=f[i][j]f[i][j1],则g[i][j]是一个0/1序列

稍微模拟一下即可发现,g[i]g[i+1],就是在0/1序列的开头加上一个1,并删去后ai个数中最考前的1,没有就不删,最终的答案就是g[n]1的个数

那么每增加一个代价,就是可以少一个这样的删去1的操作,来考虑转换这个操作

发现只关心最终序列中的1的个数,那么操作等价于,给你一个n的全是1的数组,将ai从小到大排序,每次取出数组中最小的为1的位置,如果这个位置ai,就删去1,否则不操作,令可以删到1aii为有标记的i

发现这样做,ai的顺序就不重要了,而且显然,每次删除操作的时候,只需要删去最大的ai即可,且一直直到删到一个有标记的i,此时序列的长度+1

复杂度O(NlogN),瓶颈在排序,其余操作都是O(N)

[ARC159C] Permutation Addition

显然最后的序列中,每个ai都是序列的平均值,即ai=sumn,而每次sum都会加上n(n+1)2,设sum0表示初始的sum

分类一下,当n为奇数的时候,n(n+1)2n的倍数,那么就要求sum0n的倍数

n为偶数的时候,k×n(n+1)2n2的倍数,那么加两次就是n的倍数了,当sum0n的倍数时,就直接操作,是n2的倍数时,先随便操作一次变成n的倍数,然后再看怎么弄

首先有一个很好用的策略,就是每次加上1,2,3,...,n,再来一次n,n1,...,1,那么任意两个数间的差值都不变,且发现这样一次性操作两次的话,无论n是奇数还是偶数,都能让sum加上的数为n的倍数,那么就能适中保持当前的sumn的倍数了

猜测应该会存在策略使得满足上述条件即可构造出合法的方案,显然应该会需要根据当前的sumn来调整策略,找到最大和最小的数ab,我们依旧希望保留上面那个一次性操作两次的结构,因为a是最大的,b是最小的,所以一定是希望让a相对其他数1b相对其它数+1,那么假设a就是第一个数,b是第二个数,则原本是操作1,2,3,...,nn,n1,...,1,即n+1,n+1,...n+1,现在换一下,变成操作1,2,3,...,nn1,n,...,1,即n,n+2,...,n+1,那么就实现了我们的目标

操作次数:O(NV),题目给的1e4绰绰有余

[ARC159E] Difference Sum Query

比较抽象的题目,题面翻译的有点让人误会啊,原题面在l=m+1和让t+1间写的是句号,翻译的写的逗号,一开始一直以为是只有l=m+1才能让t+1

首先把题面关于m的式子转换一下,令ci=aibi

m=atmodM×l+btmodM×ratmodM+btmodM=l+ctmodM×r1+ctmodM=l+(rl)×ctmodM1+ctmodM

因为题目说了,ci[12,2],所以ctmodM1+ctmodM[13,23]

考虑m=l+(rl)×ctmodM1+ctmodM的意义,就是取[l,r][13,23]

考虑感觉这个过程建树,每个数的节点就是当前的m,左右孩子就是左区间的m和右区间的m,显然树最多只有log32N层,也就是85.183的范围,大概就是1e2的数量级,发现这样的话,因为询问是1e4级别的,那么每次循环跑个从根到某一个点,这样的复杂度显然是可以接受的

考虑怎么求答案,先建出[c,d]的虚树,这里把所有被经过的点和边都要加入,无论是否是属于[c,d]的,发现这个树显然是满足其中序遍历出来的序列就是原系列,那么c就是最左边的那个点,d就是最右边的那个点,且相邻两点在树上高度差即为xjxj+1的差,又因为询问的都是相邻的点,显然相邻的点第一次被分离开时是其中一个被选中了,也就是说,相邻两点一定是呈祖先关系的,那么这个相邻两点在树上的高度差也即相邻两点在树上的路径长度,即它们之间边的数量,模拟一下可以发现,虚树上每条边都会被经过两次,除了c到根的路径上的边和d到的路径上的边

那么只需要计算出总的边数,以及c到根的边数和d到根的边数

那么根、cd具体在哪都是好求的,O(1e2)就可求出,考虑怎么求总的边数

因为一共有dc+1个点,所以至少有dc条边,发现剩下的没被算到边的数量就等同于虚树上的不出与[d,c]间的点,又因为中序遍历的性质,这些不在区间中的点一定是在c根和d根上的

复杂度O(1e2Q)

[ARC159F] Good Division

线性做法 ✡

首先,好的序列满足以下两个限制:

  • 长度为偶数
  • 没有绝对众数

考虑证明,若存在某一个数x的出现次数cntx恰好是序列的一半,那么显然可以一直删x和一个不是x的数来把序列删空,对于不存在这样的x的序列,只需要进行一些调整使得出现x即可

dp[i]表示前i个的答案,那么dp转移有:

dp[i]=[!check(j+1,i)&&(ij+1&1==0)]dp[j]

check(i,j)是在判断[i,j]内是否有绝对众数

显然有值的dp[i]只能是偶数的i,所以后面那个判断ij+1&1=0的其实可以省去,下文就省略不管了

考虑优化转移,记录prei表示jidp[j],那么dp[i]=prei1s,这里s记录的就是不合法的dp[j]的和

考虑怎么把si2转移到is会加上那些以i2为右端点不合法且以i为右端点合法的值,减去以i2为右端点合法以i为右端点不合法的点

  • i2为右端点不合法且以i为右端点合法

假设这个区间是[l,i],那么显然有[l,i2]有一个恰好数量为i2l+12+1的数x,且ai1ai都不是x

  • i2为右端点合法以i为右端点不合法

假设这个区间是[l,i],可以知道,肯定是ai1ai导致了某个数的数量超过了il+12,又因为在[l,i2]是合法的,也就是说在[l,i2]中是i2l+12的,那么只能是在[l,i2]中有i2l+12个,且这个xx=ai1=ai

发现上面两个都满足,要么是[l,i]有、要么是[l,i2]有一个x满足其数量恰好是区间长度的一半,这是一个很强的限制,考虑它的限制:

发现对于同一个x,如果区间[l,i]中有一半是x[l,i]有一半是x,那么显然有[l,l1]中有一半是x,即对同一个x,这样一半的区间可以拆成不包含的关系,进而可以连边,即il,其中[l+1,i]满足有一半是x的最大的l,这样会变成一种类似树状的结构,也就是会使转移变得十分有序

如果这样的边的数量允许的话,似乎我们只需要找到每个x的这种边,然后转移的时候直接转移即可,大概就是给每个点记录一个f[v]表示颜色为v的以i为右端点的这种有一半是x的区间的左端点-1的那个点的dp值之和,对于if[v]就从il转移过来即可

考虑边的数量

结论是,对于每种x,作为这种区间的左/右界的端点的数量是O(cntx)的,而显然我们的边的数量大概就是这种作为边界的点数量

考虑这样一种方法,把序列中所有为x的位置都标记为1,然后对于所有为1i,把[i,i+1]加入队列中,每次取出左端点最小的区间[l,r],如果这个区间和队列中的区间[x,y]有交,变[l,r+yx+1]塞回队列,并删除[l,r][x,y],如果不存在,那么把[l,r]放到另一个维护的队列中(注意到,实际上不是左端点最小的区间一定是某一个[i,i+1],所以这种做法说起来很高大尚的样子,其实也就是每次变成[l,r+2]罢了)

正反都做一次,可以得到所有可作为这种区间的左/右界的端点以及每个i对应的l(上文提到建边用的),显然点数是O(cntx)

复杂度的话,精细点可以O(N),一般点就O(NlogN)

cdq分治的双log做法 ✩

依旧还是绝对众数的限制:

首先,好的序列满足以下两个限制:

  • 长度为偶数
  • 没有绝对众数

考虑证明,若存在某一个数x的出现次数cntx恰好是序列的一半,那么显然可以一直删x和一个不是x的数来把序列删空,对于不存在这样的x的序列,只需要进行一些调整使得出现x即可

那么现在考虑cdq分治来维护dp

对于当前区间,[l,mid][mid+1,r],先递归出[l,mid]dp值,求出[l,mid]的后缀绝对众数,[mid+1,r]的前缀绝对众数,然后对于一个长度为len的区间,后缀的绝对众数的种数是loglen级别的

而对于一个跨mid的区间[a,b]的绝对众数,一定是[a,mid][mid+1,b]的绝对众数,也就意味着,所有跨mid的区间的绝对众数是logN级别,就可以枚举所有可能众数,算出后缀中该众数x的数量与前缀中的数量,对于一个区间[midt1+1,mid+t2],其中[midt1+1,mid]x的数量为v1[mid+1,mid+t2]的数量为v2,那么有2×(v1+v2)>t1+t2,即2×v1t1>t22×v2,要么树状数组直接求了,要么用unordered_map记录一下,然后给前后缀排个序,就可以双指针了,另一种方法是用摩尔投票,如果当前数是x+1,不是就1,然后前后缀相加大于1的合法,本质和上面那个一样

复杂度O(Nlog2N)O(Nlog3N)

[AGC007E] Shik and Travel

感觉确实简单啊,咋是黑的呢

显然要二分lim然后check,那么只需要具体考虑怎么check

题目要求每条边都要经过两次,即进入一棵子树后,必须把子树内的点遍历完了再出来,其实就是一个类dfs的过程

很自然的想到dp,设dp[u][a][b]表示u子树内,进去的那条链的长度为a,出来的为b,是否存在合法方案

发现我们只需要对每个adp[u][a][b]记录最小的合法的b即可,再进一步的,如果a1<a2,且b1b2,那么显然dp[u][a2][b2]就没有存在的必要了

这样,总的状态就是O(NlogN)的,转移是简单的,直接枚举左右儿子的dp即可,双指针优化一下就行,转移总复杂度依旧是O(NlogN)

总复杂度就是O(NlogNlogV)

P10880 [JRKSJ R9] 莫队的 1.5 近似构造

首先,因为要求的是乘积最大,所以问题转换为划分值域区间,使得每个区间的价值的乘积最大

进一步的,设当前区间的答案是v,对半拆成v2×v2,发现当v4的时候,这样一定是不劣的,也就是说,我们划分出的区间的值只可能为1/2/3

那么考虑对每个点i,求出pos[k][i]表示以i为右端点的区间的价值为k时,最大的左区间,显然如果求出这个,就能O(N)dp

考虑怎么求出这个东西,考虑从题目给定的区间入手,那么即是将当前区间中的所有数排序后就能知道,对于当前区间,区间中每个数的pos[k][i],要得到真正的pos[k][i]即是将所有pos[k][i]max即可,显然被另一个区间包含的区间是无用的,那么现在就是一些相交但不包含的区间了,即左右端点都单调递增,那么set维护一下即可,具体的就是在插入的时候更新插入的这个点的pos[k][i]和这个点后面最多2种的pos[k][i]

总复杂度O(NlogN+N)

P10882 [JRKSJ R9] ZYPRESSEN ✬✩

学会了,支配点!以前没听到过这个说法?感觉还挺有趣的,打算找几道题做

首先对值域进行分块,分成[2i,2i+1),那么可以发现,对于当前询问区间,找到第一个块内数量3的块t,那么显然块t中的前三个能直接构成一组三元组,那么如果要使得剩下的三元组比这个更优,那么一定会至少包含t之前的块中的某一个数

现在来考虑一个性质,加入我们已经确定了三元组的a,那么只需要满足abca+b>c即可,后面这个变为a>cb,又因为题目要求了a+b+c最小,所以一定有bc是相邻的

现在我们可以知道,这个a一定是被包含在t之前的块中的,那么所有的a的数量就是O(logV)的,考虑bc的包含情况

  • 如果b也被包含在t之前的块中

这样的b的数量是O(logV)的,这里相当于直接遍历出所有被包含在t之前的块中的数,然后双指针一下,一个枚举b,另一个从末尾往前维护最小的满足条件的a即可

  • 如果b不被包含在t之前的块中

此时b的数量就不是O(logV)的,来考虑预处理

注意到,一个数能被选做a,设其所属块A,一定有当前询问区间包含的数中,属于块A的不超过2个,找到这个数左边第二个属于A的数L,右边第二个属于A的数R,那么一个询问区间[l,r]只有满足[l,r](L,R)才有可能会使得这个数成为A

那么显然,这样的所有(L,R)的长度之和是O(NlogV)的,那么就可以对于每个数,去预处理它的(L,R)区间内的可能会变成答案的三元组了,这个其实就是找支配点

再来考虑限制a>cb,把数x变成xa,那么肯定只有当caba1才有可能满足a>cb

ca=ba时,是一定满足的,考虑求出这个情况的支配点,似乎是支配点的经典做法?

此时维护前/后缀的最小值序列,这里维护后缀的,那么就是从L+1R1枚举同一种向下取整值的i,考虑当前加入的数ai,首先有这样一个性质,对于j1<j2,两者都是目前序列中数,且它们是相邻的,显然点对k(j1,j2)(k,i)没有(j2,i)优,也就是说,显然只有i和在序列中的点j才有可能构成支配点,已经被弹出不在序列中的就不用管了

那么当把ai加入队列中时,它会删去末尾ai的那些aj,此时把这些弹出的j和当前i组成的点对(i,j)加入支配点
,这部分的支配点数量显然是线性的,再来考虑那么不会被弹出的j,对于不会被弹出的j1<j2,这里j1j2相邻,显然点对(j1,i)没有点对(j1,j2)优,也就是说,这部分只用加入一个点对(j,i)即可,这里的j是弹出后序列中当前的最后一个j,这个数量显然也是线性的

再来考虑ca=ba+1,对于等于caai,以及等于baaj1aj2,有j1<j2,考虑以下几种情况:

j1<j2<i,此时显然(j1,j2)优于(j1,i),那么此时只会加入(j2,i)

i<j1<j2同理只会加入(i,j1)

也就是说,对于i,只会加入其左边第一个和右边第一个ca1的值作为支配点,那么这部分总的点数就是O(NlogV)

总复杂度O(NlogVlogN+qlogV)

CF2019C Cards Partition

sum表示牌的总数,那么有sum=sz×len,其中sz是牌组的数量,len的每个牌组的大小,显然有lenn

根据鸽巢原理,可知道只要szmaxci,就能使得每个牌组中没有相同的牌了,其中ci表示当前第i种牌的数量

显然最优情况下有:maxci=max(maxai,sumn),把sum拆开可以得到szmax(maxai,sz×lenn),而又因为lenn,所以一定有szsz×lenn,那么就只需要szmaxai即可

那么问题就变成找到最大的len,使得存在szszmaxai)满足len×sz[sum0,sum0+k],这里的sum0=ai,即sz[sum0len,sum0+klen],所以只需要满足sum0lensum0+klenmaxaisum0+klen即可

先只考虑后面这个限制,此时可二分或直接算出满足条件的最大的len,显然有可能不满足前面那个条件,注意到1len都是满足后面那个条件的,且1一定会满足第一个条件,又因为lenn,所以直接判当前len是否满足第一个条件,不满足就

复杂度O(N)O(N+logV)

CF2019D Speedbreaker

若已确定从城市t开始,那么显然先找到ai最小的那么i,设它们中最小的为l,最大的为r,那么显然当前合法的充要条件是max(r,t)min(l,t)+1ai

再找到第二小的,aj,设为aj的点对应的区间为[a,b],那么现在总的会覆盖到的就是[min(l,a,t),max(r,b,t)],只需要这个区间的长度aj即可

然后就这样一直判下去

发现只要当前总区间(即[min(l1,l2,...,lk),max(r1,r2,...,rk)])包含了t,那么之后的就没区别了

考虑先找出每个前缀的总区间,枚举当前城市t,二分到第一次区间包含t的位置k,则首先k及之后的只需要满足前缀的总区间长度当前的a的大小即可,对于之前的,显然要么全都在t的左边,要么全都在右边,此时它们对应的真正的区间会增加一部分,以全部在左边为例,假设当前区间为[l,r],那么实际应该是[l,t],也就是说,长度从rl+1变成了tl+1,那么变成满足aitl+1,只需要求出最小的ai+l1,判断是否t即可

复杂度O(NlogN)

CF2019E Tree Pruning

枚举最终叶子到根的距离len,那么显然只有位于一个深度为len的点x到根的路径上的点才能保留下来,那么虚树即可

复杂度O(NlogN)

CF2018D/CF2019F Max Plus Min Plus Size

唐了/ll

首先能知道必选最大值,证明考虑设最大值为mx,当前最大值为x,那么如果mx可以直接选进当前序列中,那就选,显然此时最大值为mx,如果不能选,最劣的情况就是和mx相邻的两个数都被选了且都不是最小值,发现此时答案的增量为1+mxx,显然啊mxx1,那么就一定不劣

现在考虑来维护最小值mn,从大到小枚举mn,每次相当于插入了一些数,发现此时会有一些块,且块与块之前显然互不干涉,如果块长度为len,那么显然最多能选len2,所以此时答案大概是ileni2的样子,但是注意到我们必须要选到最大值,所以对每个块i,考虑怎么算f0(i)f1(i)分别表示当前块不保证选到最大值的最大数量和保证选到最大值的最大数量

显然f0(i)=leni2,如果块i中不存在最大值,那么f1(i)=0,否则分类一下,发现当leni为偶数时,一定能选到leni2个,而leni是奇数时,如果奇数位上存在最大值,那么就是leni2,否则就是leni2

并查集乱搞就行,复杂度是O(NlogN)

CF2018E1/E2 Complex Segments ✯✩

好牛啊

先简化一下题意,就是要求每个子集都是一个团,且团与团之间没有边,且显然一个团中必存在一个点,使得所有边都包含了它,那么其实就相当于把序列划分成了很多段,然后每个团的边在被完全包含与当前段中的边中选

首先看到E1的数据范围,2e4,很根号,考虑根号分治

因为题目要求sz×len,其中sz是每个子集的大小,len为数量,且我们知道,sz×lenn,也就是说,有:

  • szBlennB
  • sz>Blen<nB

那么上面那种情况取sz来算,下面取len来算

考虑已知sz,求最大的len,考虑dp,记dp[i]为只考虑前i,最大的len,注意到,若当前段的右端点为i,满足区间[l,r]中团的大小szl是一段前缀,那么显然找到最大的那个l,转移就有dp[i]=max(dp[i1],dp[l1]+1)

然后又可以发现,当i+1时,l也是递增的,而根据团必有一个所有边都经过的点,只需要用线段树维护一下当前区间内的点被区间内的边覆盖的次数即可

那么可以O(NlogN)完成一次找len

若固定len,因为显然有sz越大,找到的len越小,所以二分到对应len大于等于当前len的最大的sz即可

那么这部分复杂度是O(BNlogN+NBlog2N)的,取B=(NlogN)即可取得最优复杂度O((NlogN)32),可以过掉easy version

考虑优化,这里把查找len的复杂度优化到O(Nα(N))

突然想起我之前算复杂度都把α(N)logN算,蚌埠住了

首先把区间变成不交的,显然可以有在新的区间有交当且仅当在原先的区间有交

将原本维护的覆盖次数序列ci替换成di,满足di=maxjicj,即后缀最大值序列,又因为现在的区间是不交的了,所以显然可以发现,didi11,所以现在又改为维护di的差分序列ci

考虑变化,对于当前维护的区间[l,r],现在让r+1,如果以r+1为右端点的区间[a,r+1]是属于[l,r]的,那么cr+1=1[1,a1]中最后一个ck=1ck变成0,没有就不变;从l变成l+1时,如果以l为左端点的区间[l,b]属于区间[l,r],那么会有[l,b]中最后一个ck=1ck变成0

这样复杂度就是O(Nα(N))的了

总复杂度变成O(BNα(N)+NBlogNα(N)),总复杂度O(NNα(N)logN),题解说的是(NNα(N))啊,不知道是直接剩了后面那个logN还是我唐了其实没有这个

感觉很卡常,卡了几下还没卡过去,摆烂了喵

O(NN)的做法,https://codeforces.com/blog/entry/134445,但是没太懂,脑子想不动了,等以后想看了再回来看(

posted @   LuoyuSitfitw  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示