T1
不会题解里面倍增的做法,就写了可持久化单调栈过了
一开始以为自己不会写,后来就写过去了挺开心
题解里面的做法是原来那个找到每个点上面第一个比它大的数,然后建出来一个新树
每次跑倍增
感觉会比较好写吧……
T2
首先发现一个任意两个节点都有边的有向图的最小环必然是三元环
那么这个题目就变成了三元环计数
空图简单随便做
考虑有些边的问题
这里补学了无向图三元环计数,感觉是个高妙的算法
首先对于所有点记录度数
对于每条边建出来新边:度数小的往度数大的,或者度数一样按照标号小往大
然后每次对于新的图,如果存在 (<u o v>,<u o w>,<v o w>) 那么就是一个 ((u,v,w)) 的三元环
这样做之后直接扫 (u) 的出点,(v) 里面的出点看是不是存在 (w)((c++11) 的 (auto) 写起来真爽)
复杂度是 (O(msqrt m)) ,以下是证明:
对于原图上面出度不大于 (sqrt m) 的点,新图上面的出度不会小于原图上的度数
如果大于 (sqrt m) 那么这样的点的出度不会大于 (sqrt m) ,因为只能向度数大于之的点连
这里运用了 (m=sqrt m imes sqrt m) 的性质
这就做完了
然后回到本题
上述算法可以解决 (Subtask 1) 正解是进一步的
其实考试的时候想差不多了,只是最后半小时才发现这个东西只能是三元环
后面的东西考虑环必然不在一个点的出点里面选两个
然后推一下就行了
其实以后也可以试一下这样的思想:考虑一个环出现的概率
那么就是说减掉 (frac {u_i(u_i-1)}2+frac {out_i u_i}2 +out_i(out_i-1))
这里 (u_i) 是没有被确定的点的数量,即 (n-in[i]-out[i]-1)
T3
原来看题解的时候没有研究明白,当时就会了个能过那个题目的做法,没看更优解……
以后不妨放慢脚步
考虑每个 ((i,j)) 从 ((-a_i,-b_i)) 到 ((a_j,b_j)) 的每条路径 是只会经过 (x+y=0) 一次
那么对于直线上面的整点维护方案并加和即可
T4
堆维护一下即可