2019集训队作业做题实况[1](1-30):

50-1(19.10.23)(树的性质):

https://codeforces.com/contest/516/problem/D

https://codeforces.com/contest/516/submission/63242051

大意:
给一棵树,定义\(d[x]=max(dis(x,y))\)

求一个联通块\(S\),使得\(max(d[x∈S])-min(d[y∈S])<=l\),求\(max(|S|)\)

\(d[x]\)肯定是\(x\)到直径两个端点的最大值。

然后发现可以直接lct维护联通块大小。

发现性质,若以d最小的为根建树,\(d[fa[x]]<=d[x]\)

那么就是扫描线,对于x,可以用树状数组直接统计子树里\([d[y]<=d[x]+l]\),因为连续。

上网发现还可以直接用并查集维护联通块大小,删掉时直接减1,并查集不用变,还是因为连续。

50-3(19.10.24)(计数+分治):

https://atcoder.jp/contests/agc023/tasks/agc023_e

https://atcoder.jp/contests/agc023/submissions/8106222

大意:

求满足p[i]<=a[i],p是一个排列,p的逆序对数和。

考虑求p的方案数。

从大到小给每个数选择位置,这样的话就可以确定这个数可以放的位置数。

\(cnt[i]=\sum [a[j]>=i]\)\(Ans=\prod cnt[i]-(n-i)\)

要考虑逆序对数的话,枚举两个\(i,j(i<j)\),假设\(a[i]<=a[j]\)

\(p[j]>a[i]\)时,不会产生逆序对数,将\(a[j]\)调整至\(a[i]\),发现恰好有一半的排列就是\(p[i]>p[j]\)的。

\(a[i]>=a[j]\),考虑用总数-顺序对数,顺序对数和上面一样,把\(a[i]\)调整至\(a[j]\)

若调整\(a[i]<=a[j]\),则\(cnt[x]--,x∈(a[i],a[j]]\),对合法排列的影响可以预处理\({cnt[i]-n+i-1\over cnt[i]-n+i}\)的区间积来实现目的。

这样得到了\(O(n^2)\)的做法。

用线段树分治来统计答案就是\(O(n~log~n)\)的。

50-2(19.10.24)(概率+积分):

https://atcoder.jp/contests/agc032/tasks/agc032_f

https://atcoder.jp/contests/agc032/submissions/8109887

大意:
一个圆被随机\(n\)条直径分割,设\(s\)为一个扇形的面积,求\(min(|s-1/3|)\)

第一步需要一个不可能想到的转换考虑把一条线定位0°,然后划分成三个区域,0-120°,120-240°,240°-360°

这个区域里的划分看作三种颜色红绿蓝,然后全部\(mod~120°\)搞到\(0-120°\)里,发现问题变为\(0-120°\)里,随机\(n-1\)条划分,颜色也随机,求颜色不同的划分的最近距离,注意0°视作有一条红色的,120°视作有一条蓝色的。

\(n-1\)条弧把1/3的区域划分成了\(n\)段。

\(E(i)\)表示长度为1的线段分成\(n\)段第\(i\)长段的期望长度。

通过推理可以得到:

$Ans=

\(Ans=\sum_{i=1}^n 3^{i-1}*(E(i)-E(i-1))*{1\over 3}\)

即一条线段两个点同色的概率是\({1 \over 3}\),要使\(E(i)-E(i-1)\)被统计到,则\(i\)以前的线段都要同色,所以是\(3^{i-1}\),长度上限是\({1\over3}\),还要乘\({1\over 3}\)

问题在于求\(E(i)\)

先求\(E(1)\),设\(P(i)\)表示长度为1的线段分成\(n\)段最短线段长度\(>=i\)的概率。

\(E(1)=\int_{x=0}^{1/n} P(x) ~dx\)

\(P(x)=(1-nx)^{n-1}\),下面将解释这个东西:

考虑把线段分为\(a(a->∞)\)段,在其中随机选\(n-1\)个点就分成了\(n\)段,方案数是\(a^{n-1}\)

现在要求每一段线段的长度都\(>=x\),可以理解成少了\(nx*a\)个点,还剩\(a-nx*a\)个点,方案数是\((a-anx)^{n-1}\)

则概率就是\((a-anx)^{n-1}/a^{n-1}=(1-nx)^{n-1}\)

\(\int_{x=0}^{1/n} (1-nx)^{n-1}~dx\)

\(=\int_{x=0}^{1/n} x^{n-1} ~ dx\)

\(=1/n^2\)

所以\(E(1)={1 \over n^2}\)

然后推\(E(2)-E(1)\)

这个就比较简单了,\(E(2)\)相当于还剩下\(1-E(1)*n\)的长度,分给\(n-1\)段,最短期望长度。

那么就是\(E(2)=(1-{E(1)*n})/(n-1)^2=n*(n-1)\)

通过数归可以得到:\(E(k)-E(k-1)={1\over n*(n-k+1)}\)

那么这题的答案就是:\(Ans=\sum_{i=1}^n {1 \over 3^in(n-k+1)}\)

49-1(19.10.26)(决策+贪心):

https://codeforces.com/contest/506/problem/C

https://codeforces.com/contest/506/submission/63412933

https://codeforces.com/contest/506/submission/63421859

大意:

有n个竹子,第i个竹子长度为h[i],每天的结束会长高a[i]
现在有m天,每一天可以做k次操作,每次操作可以选择一个竹子砍掉p,即高度h[i]=max(h[i]-p,0)
你需要最小化m天结束后最高的竹子的高度
n<=100000,m<=5000,k<=10

首先二分答案x。

solution1:

然后发现直接顺着搞无法决策每次机会给谁。

于是逆着搞,问题等价于,一开始每根竹子的高度是x,每次先降低a[i],操作可以拔高p,要求每根竹子任何时候高度非负,且最后的高度>=h[i]。

那么这个问题十分简单,主要是没了max(0,h-p)这种不好考虑得东西,先把所有操作留着,当一个竹子要h<0时,就给他加p,最后再填到h[i],看操作够不够用就行了。

要用\(priority\)_\(queue\)\(set\)被卡常。

solution2:

每根竹子至少要\(c[i]=\lceil {x + a[i]* m - h[i] \over p}\rceil\),事实也不会要更多次。

假设要多了一次,不如不做前面的那次不满p的,效果是一样的。

然后设\(d[i][j]\)表示第i根竹子的第j次操作至少要在\(d[i][j]\)天后。

\(d[i][j]\)怎么求是个好问题。

先思考\(c[i]\)刀要满足什么才能合法,就是它们的效果和\(>=x+a[i]*m-h[i]\)

也就是\(>=(c[i]-1)*p+(x+a[i]*m-h[i])~mod~p\)

则对于任意前\(j\)刀,砍的时候要满足:

\(h[i]+(d[i][j]-1)*a[i]>=(j-1)*p+(x-h[i])~mod~p\)

搞一下\(d[i][j]\)就出来了。

接着扫一遍,看看够不够用就好了。

1-2(19.10.26)(性质+线段树):

https://codeforces.com/contest/674/problem/G

https://codeforces.com/contest/674/submission/63429991

大意:
给出n个数,每次可以对一个区间进行整体赋值,或者询问一个区间频率\(>=p\%(20<=p<=100)\)的数。

在编程之美上看过这样一个问题:
有n个单词,其中有k个单词频率\(>={1 \over k +1}\),其它的都小于\({1\over k +1}\),要求利用\(O(k)\)的空间找出这k个单词。

考虑k=1的时候,只需要记录一个单词和一个计数器,如果新的单词和记录的一样,计数器+1,否则-1,当计数器=0时,记录的单词变为新的单词。

\(k>1\),类似的,就记k个不同的单词和计数器,加入一个新的,有相同的就把计数器+1,否则计数器全部-1,有计数器=0的就替换。

证明就是把上面的看做每次找k+1个不同的单词删掉,最后剩下的一定是那k个单词。

对于这道题,可以看做做\(k=\lfloor100/p\rfloor\),用线段树维护,\(O(k^2)\)暴力合并两个表即可。

时间复杂度:\(O(n~log~n~*k^2)\)

49-2(19.10.31)(势能分析,线段树)

https://codeforces.com/contest/679/problem/E

https://codeforces.com/contest/679/submission/63884902

大意:

有一个序列,每次可以区间赋值,或者区间加,如果区间加完后这个区间有42的次幂,那就继续求,还有询问一个的值。

42的次幂在int范围里的只有6个。

我们对每一个数设一个\(dis[i]\)表示\(a[i]\)到下一个42的幂的距离。

区间加法相当于dis区间减法,当减到<=0时,就顺便判一下并改一下,如果没有2操作的话,因为一个数最多被搞6次,复杂度就是:

\(O(n~log~n*6)\)

考虑有了2操作,如果一个区间实际值一样,且dis<=0,那么一起修改,容易证明,复杂度还是:

\(O(n~log~n*6)\)

48-1(19.10.31)(tarjan缩强联通分量)

https://codeforces.com/contest/555/problem/E

https://codeforces.com/contest/555/submission/63894938

太水了不讲了。

49-3(19.10.31)(转换模型+贪心+树形dp)

https://atcoder.jp/contests/arc098/tasks/arc098_d

https://atcoder.jp/contests/arc098/submissions/8223881

大意:
给出一个联通无向图,走到一个点的时候至少要有\(a[i]\)的金币,可以花下\(b[i]\)的金币买下这个点,求最少要多少金币才能把所有点买一遍。

我只能想到先选\(a[i]-b[i]\)大的比较优,但是这只能用于完全图的情况,然后就不会了。

事实上可以这么转换问题,就变得明了。

\(c[i]=max(0,a[i]-b[i])\),要保证只要在这个点上,\(金币数>=c[i]\)

这个问题,不难想到把\(c[i]\)最大的提出来,越早买它越好。

但是它的邻节点可以分成多个联通块,如果一开始就买了,可能就不能走到了其它地方了。

所以一定留在最后一个联通块进去前买。

\(sumb[i]\)表示i为根的来联通块的\(\sum b\)

\(g[i]\)表示i为根的联通块所需的金币数\(-sumb[i]\)

考虑\(g[x]\)怎么转移,直接枚举最后走到的联通块y,因为\(c[x]\)是子联通块里最大的,所以一定能不用额外的金币通过其它子树,对于这个联通块所需的额外金币是\(max(g[y],c[y]-sumb[y])\),取所有y的最小值即可。

48-2(19.10.31)(辣鸡结论题):

https://atcoder.jp/contests/agc032/tasks/agc032_e

https://atcoder.jp/contests/agc032/submissions/8226893

大意:

把2n个数分成n对,使得\(max((a[i]+a[j]) ~mod ~m)\)最小化。

大胆猜想可以找到一个分界点,使得左边第一个和最后一个,第二个和倒数第二个……右边也是如此

这样会最优,证明可以看题解那6个图,然后用不等式做做发现就是对的。

题解:https://img.atcoder.jp/agc032/editorial.pdf

于是二分这个分界点就好了。

48-3(19.10.31)(博弈+最优化决策):

https://atcoder.jp/contests/agc032

https://atcoder.jp/contests/agc023/submissions/8229211

大意:

数轴上\(n\)个点,第i个点是\(x[i]\),人数为\(p[i]\)

一开始所有人在车上,车在\(S\)上,每次进行投票,往正或者往负走,到达一个\(x[i]\)时,\(x[i]\)上的\(p[i]\)人会下来。

每个人秃顶聪明,会希望自己在车上的时间最小,输出最后下的人的时间。

*想题两小时,做题五分钟——论atcoder做题感受。

很不自然地考虑\(1\)\(n\)两个地方的人的决策。

\(p[1]>=p[n]\),即使\(n\)上面的人把车往右边拉,走到了\(x[n-1]\),由于\(p[1]>=p[n]\),车还是往回走。

也就是\(n\)一定在\(1\)的后面,\(T(n)=T(1)+x[n]-x[1]\),所以\(n\)上面的人不如让\(T(1)\)最小,也就是跟着\(1\)决策。

\(p[1]+=p[n]\),现在变成了\([1-n-1]\),求\(T(1)\)的子问题,递归求解。

\(p[1]<p[n]\)的情况同理。

直到最后只剩一边的人,那么就不用决策了,直接走。

43-1(19.10.31)(分段矩阵乘法):

https://codeforces.com/contest/575/problem/A

https://codeforces.com/contest/575/submission/63930223

一眼题不说了,mdzz要判k=0和k=1。

47-1(19.11.1)(矩阵乘法+倍增):

https://codeforces.com/contest/576/problem/D

https://codeforces.com/contest/576/submission/63987413

\(T(i)\)表示i时间,从1出发,能到那些点。

\(F(i)\)表示,\(i\)以前的边所形成的转移矩阵。

\(T(n+1)=T(n)*F(n)\)

而这些边按时间排序,之间的\(F\)是一样的。

用倍增去试即可,注意维护的是\(F(n)^{1..x}\)的或和。

47-2(19.11.1)(结论+二分图网络流):

https://atcoder.jp/contests/agc029/tasks/agc029_f

https://atcoder.jp/contests/agc029/submissions/8241674

什么LJ猜结论题。

我只能把题解复述一遍了。

对于一棵树,当我们去掉一个点后,剩下的点和边必须有完美匹配,可以理解为以这个点作根,每个点和它到父亲的边匹配。

对于每个点都要满足这个,这显然是有解必要条件。

其实这还是充分条件。

考虑分别以u、v作根,把两个完美匹配图取并集,你会发现一定有一条从u到v的路径,因为u、v的度数=1,而其他点的度数都=2。

这也说明假设以\(u\)为根,跑完美匹配,如有\(x,y\in s[i],s[i]~choose~x\)\(x->y 连边\)

那么从u开始dfs,若满足之前的必要条件,一定能够走到其它的所有点(相当于沿着路径更改匹配的选择)。

这恰好也是一组答案。

10-1(19.11.2)(点分治二分树上凸函数):

https://codeforces.com/contest/566/problem/C

https://codeforces.com/contest/566/submission/64055933

考虑一条链的情况,考虑选的位置是x,则代价=\(\sum abs(p[i]-x)^{1.5}*w[i]\)

这是若干凸函数的和,还是一个凸函数。

那么链上直接二分即可。

树上用点分治二分即可,每次看往哪个子树走优。

36-1(19.11.2)(库默尔定理+数位dp):

https://codeforces.com/contest/582/problem/D

https://codeforces.com/contest/582/submission/64057294

很久以前做过的。

https://blog.csdn.net/Cold_Chair/article/details/77488682

9-2(19.11.2)(set):

https://codeforces.com/contest/674/problem/D

https://codeforces.com/contest/674/submission/64057984

37-2(19.11.4)(动态规划):

https://codeforces.com/contest/704/problem/B

https://codeforces.com/contest/704/submission/64202127

不错的一道拆绝对值dp题。

x是递增的,那么我们不需要考虑具体是谁和谁匹配,只需要知道方向即可。

从左往右做,左边就可以剩下两类点,一类是缺一条来自右边的入边,一类是缺向左的出边,一个点可以同时是第一类和第二类。

\(f[i][j][k]\)表示前i个点,一类点j个,二类点k个,最小值。

然而在不考虑起点和终点时,\(j=k\),因为有入必有出。

经过起点后,第二类比第一类多一个,经过终点后,第一类比第二类多一个。

这样就少了一维。

dp时可以记当前第二类比第一类多了h=0、-1、1个点。

转移时注意除了一开始和最后,第一类和第二类点至少要有一个,不然就不联通了。

4-3(19.11.4)(构造):

https://atcoder.jp/contests/agc030/tasks/agc030_c

https://atcoder.jp/contests/agc030/submissions/8291382

发现竖着横着都不行,于是就斜着。

使\(n=k,color[i][j]=(i+j)\%n+1\)

你得到了和横着竖着一样的解法。

发现这个东西,每一条斜线可以塞两个颜色……也不会错……

2-3(19.11.4)(动态规划):

https://atcoder.jp/contests/agc030/tasks/agc030_d

https://atcoder.jp/contests/agc030/submissions/8292283

考虑设\(f[i][j]\)表示若干操作后,\(a[i]>a[j]\)的方案数。

若当前是交换\(x,y\)

对f的影响就是,要么就是×2,即\(i、j\)\(x、y\)无关,要么就是很简单的转移。

所以维护个整体×2标记,每次只修改相关的,最后统计一下就好了。

13-2(19.11.5)(二元关系网络流):

https://atcoder.jp/contests/agc038/tasks/agc038_f

https://atcoder.jp/contests/agc038/submissions/8299844

考虑每个环只有转一下和不转,我们可以对i讨论一下贡献。

\(1.p[i]=q[i]=i\)

不管怎样都不会有贡献。

\(2.p[i]=q[i],p[i]≠i\)

只有两个都不转或两个都转才没有贡献。

\(3.p[i]≠q[i],p[i]=i\)

只有q转了才有贡献。

\(4.p[i]≠q[i],q[i]=i\)

只有p转了才有贡献。

\(5.p[i]≠q[i],p[i]≠i且q[i]≠i\)

只有都不转才没有贡献。

由第2条可以得到两边的方向是相反的。

不妨设\(p\)属于\(S\)即选了,\(q\)属于\(T\)即选了。

连边的话比较显然,不写了。

4-2(19.11.5)(概率+生成函数|min-max容斥+dp):

https://atcoder.jp/contests/agc038/tasks/agc038_e

https://atcoder.jp/contests/agc038/submissions/8303241

\(P(i)\)表示i还没有结束的概率。

\(Ans=\sum_{i>=0}P(i)\)

直接算\(P(i)\)并不好算。

考虑设\(Q(i)\)表示第i步已经结束的概率。

\(P(i)=1-Q(i)\)

\(Q(i)=\sum_{d[j]>=b[j]且\sum d[j]=i}{i! \over d[j]!}*\prod({a[j]\over \sum a})^{d[j]}\)

写成EGF:
\(Q(x)=\prod (e^{{a[j]\over \sum a}x}-\sum_{k=0}^{b[j]-1}({a[j]\over \sum a})^k/k!*x^k\)

\(P(x)=e^x-Q(x)\)

暴力展开求出\(P(x)\)

考虑最后\(P\)的形式是:
\(\sum c[i][j]*e^{{i\over \sum a}x}*x^j\)

忽略\(c[i][j]\),相当于求\(e^{tx}*x^j\)每一项系数和。

\(=\sum_{i>=0}t^i*x^j/i!*(i+j)!\)

这个是EGF,所以乘上\((i+j)!\)

\(=j!\sum_{i>=0}t^i*C_{i+j}^j\)

\(=j!*({1\over 1 - t})^{j+1}\)

还可以min-max容斥+dp,只要有意识的靠,再推推式子就能出来,这里不讲了。

31-1(19.11.6)(扫描线):

https://codeforces.com/contest/538/problem/H

https://codeforces.com/contest/538/submission/64347902

这个题除了特别长以外就真的只是特别长了。

先对每个联通块进行单独考虑。

不是二分图直接无解。

是二分图的话,对二分图的两边分别求区间交。

现在问题就是看每一个二分图的两边分别分到那边。

假设一个二分图的两个边的区间交分别为\([l1,r1][l2,r2](l1<=l2)\)

一共有三种情况:

\(l2,r2<=r1\)

\(l2<=r1,r2>r1\)

\(l2>r1\)

对这三种情况分别看\(n1\)属于每一个子区间时,\(n2\)能属于哪个区间。

然后扫一遍,用个堆来维护即可。

最后还要还原答案,想打出题人。

29-1(19.11.6)(2-SAT):

https://codeforces.com/contest/568/problem/C

https://codeforces.com/contest/568/submission/64362913

比较显然由字典序去填每一位。

问题相当于有一些为已经确定,问是否有解。

每个点拆位选'V'还是选'C',对一开始的边,正反都连一下。

已经确定的点,可以直接dfs,或者连一条边继续判。

注意要判只有'V'或者'C'的情况。

22-2(19.11.6)(几何+简单线性规划):

https://codeforces.com/contest/685/problem/C

https://codeforces.com/contest/685/submission/64371840

考虑二维的时候,我们把曼哈顿变成\((x+y,x-y)\),这样就变成了矩形。

同样的,三维我们把它变成四维的:
\(a=x+y+z\)

\(b=x-y-z\)

\(c=-x+y-z\)

\(d=x+y-z\)

二分答案ans后,求四维空间的交。

当然并不是有交就有答案。

若有\(x,y,z\)满足\(a,b,c\),它不一定满足\(d\)

所以要限制一下\(d\),事实上\(d=a+b+c\),专门凑好的。

那么这里做一个简单的线性规划可以解出\(a,b,c\)

注意\((x,y,z)\)要是整数,所以反解后得是整数。

\(x=(a+b)/2\)

\(y=(a+c)/2\)

\(z=(b+c)/2\)

可以得出\((a,b,c)\)的奇偶性相同即可。

解出最优答案的\((a,b,c)\)后就好了。

不知道为什么WA on 6,可能是解\((a,b,c)\)时出了一点小问题,正负波动个2就能过了。

30-2(19.11.7)(dp):

https://codeforces.com/contest/704/problem/C

https://codeforces.com/contest/704/submission/64453278

每个点只出现两次,所以形成的图的每个联通子图要不是是环要不是链。

直接dp,要判一堆\(k=1\)带来的猎奇情况。

6-3(19.11.7)(mst):

https://atcoder.jp/contests/arc093/tasks/arc093_c

https://atcoder.jp/contests/arc093/submissions/8324595

先做出个Mst。

设mst的边权和为sum。

\(sum>X\),显然\(ans=0\)

\(sum=X\),设能在mst上的边有ca个,不在有cb个。

考虑这ca个只要不全部同色就行了。

\(Ans=(2^{ca}-2)*2^{cb}\)

\(sum<X\),设替换mst上的最大边后\(sum>X\)的有\(cb\)个,\(sum=X\)的有ca个。

显然这ca个至少有一个和\(sum<X\)的异色。

所以\(Ans=2*(2^{ca}-1)*2^{cb}\)

10-2(19.11.8)(SAM+dp):

https://codeforces.com/contest/700/problem/E

https://codeforces.com/contest/700/submission/64496361

考虑把这个出现两次卡的紧一些。

比如说一定有一次是后缀,这样答案并不会变。

但是因为变成了后缀,所以可以在SAM上dp。

考虑SAM上一个节点x代表着长度在一个区间的串,设\(f[x]\)表示x代表的最长串的答案。

\(f[x]\)可以由\(f[fa[x]]\)转移过来,至于为什么只考虑最长串之间的dp,可以看:

https://blog.csdn.net/litble/article/details/81179442

的证明。

判断\(f[x]\)能不能由\(f[fa[x]]\)转移过来可以预处理\(right\)集的线段树。

注意对每个x要多记\(pos[x]\),含义为:
\(pos[x]=y|y是x的祖先且f[x]=f[y]且min(dep[y])\)

每次实际转移不是\(x\)\(fa[x]\),而是\(x\)\(pos[fa[x]]\)

13-1(19.11.8)(构造+欧拉回路):

https://codeforces.com/contest/528/problem/C

https://codeforces.com/contest/528/submission/64499842

胡乱构造题,自己造出来也不知道对不对。

首先度数是奇数的点肯定要补成偶数的嘛。

然后考虑对每个联通块,每个点都是偶数的度数,可以拉一条欧拉回路。

如果欧拉回路的长度是偶数,那么只要正-反-正-反…就可以满足题目条件了。

所以如果长度是奇数,随便在一个点那里加一个自环。

19-1(19.11.8)(kruskal重构树+线段树):

https://codeforces.com/contest/571/problem/D

https://codeforces.com/contest/571/submission/64509298

写完后看了别人的做法感觉自己弱爆了。

当时一看这题,把类似Kruskal重构树的东西建出来,这样一个时间内的联通的点就在一个子树里了。

然后通过线段树来打标记求出每个点最近被删的时间。

再通过线段树区间加求和来搞定一个点在一个时间以前的答案。

由于就是要做两遍几乎一样的东西,所以代码达到了200行,虽然写起来很快。

23-1(19.11.8)(2-sat构造解):

https://codeforces.com/contest/587/problem/D

https://codeforces.com/contest/587/submission/64526348

考虑每个边拆成选和不选。

同一颜色的边在同一点可以得到限制。

在同一点的边可以得到不能同时选的限制,这里新建一些前缀后缀的虚点来搞。

然后二分答案,边权>ans的不能选,跑2-sat看有没有解。

最后再随便给出一组解,这好像是我第一次写构造解。

可以看这篇博客,有许多证明:
https://blog.csdn.net/litble/article/details/80404751

posted @ 2019-10-23 22:23  Cold_Chair  阅读(698)  评论(1编辑  收藏  举报