模拟77—「最大或· 答题· 联合权值?改· 主仆见证了 Hobo 的离别」
最大或
可以发现一个贪心策略,就是如果存在一个最大的 \(k\), 同时有 \(2^k,2^k-1\) ,那么我们肯定要构造 \(2^{k+1}-1\)
如果没有,那么就把最高位选成 \(1\) , 然后 \(l,r\) 同时去掉最高位,加上最高位的贡献,变成了子问题。
并且感觉这个方法可以扩展到异或,只不过去掉最高位的同时不能加贡献。
答题
折半+二分答案+单调指针,是之前一个题的弱化版(模拟22 - f)。
那就写一下 f 的题解吧。
照样先折半,现在的问题是如何快速求出一个 \(x\) 的 \(f(x)\) 。
发现一半按位考虑都可以贪心,这个也不例外,如果高位已经大了那么后面无力回天。
所以只要记录每一位翻转\不翻转下的逆序对个数,最后加起来就好了。
然后二分一个 \(f(res)\) , 看比他小的个数是不是 \(k\) 个。
有个不用考虑边界的方法就是同时扫出小于的和小于等于的,如果夹在中间就说明合法。
给一个代码供参考(今天T2的check部分)
inline bool check( int x ){ // return 0 means x is needed to up
int ansl = 0 , ansr = 0 ;
for( R i = 1 , j = sr [0] , kk = sr [0] ; i <= sl [0] ; i ++ ){
while( ( j >= 1 ) && sl [i] + sr [j] > x ) j -- ;
while( ( kk >= 1 ) && sl [i] + sr [kk] >= x ) kk -- ;
ansl += j , ansr += kk ;
} if( ansr < k ){
if( ansl >= k ) printf( "%lld\n" , x ) , exit( 0 ) ;
else return 0 ;
} else return assert( ansl >= k ) , 1 ;
}
然后就是已知 \(f(res)\) 求 \(res\) 了,复杂度正确的做法就是在一边开桶扫另一边,类似于主席树找第 \(k\) 大 。
联合权值?改
入门了一下无向图三元环计数。
把无向图定向成有向图,方向是从度数大向度数小,如果度数相等,从编号小到编号大。
这样易证新的图是有向无环的。
然后先枚举点,再枚举出边,再枚举出边的出边暴力判环。
复杂度为 \(\sum_{i}^{m} out_i\) ,\(out_i\) 代表有向图中 \(i\) 的出度,\(drgee_i\) 代表原图中 \(i\) 的度 。
证明一下 \(m\sqrt m\) 的复杂度。
若没有 \(drgee_i>\sqrt m\) ,则 任意\(i , out_i \leq \sqrt m\) 复杂度显然对。
否则,若 \(drgee_i > \sqrt m\) , 由于度数小向度数大的连边,所以他连向的点度数必定大于 \(\sqrt m\) ,这样的点只有 \(O(\sqrt m)\) 个,所以\(out_i \leq \sqrt m\) ,复杂度也是正确的。
同样可以证明一个结论,一张无向图最多有 \(m\sqrt m\) 个三元环,因为我们上述做法可以找到所有三元环,而我们最多只能找 \(m\sqrt m\) 个。
所以第一问按权值排序,找到一个合法的就退出。
如果不合法,必定是有三元环,而三元环只有 \(m\sqrt m\) 个。
第二问直接用所有答案容斥掉三元环的答案。
所有答案的形式是 \(\sum_i\sum_j a_i*a_j\) 。
对于这种需要枚举两个计算的,可以考虑这个式子 \(\sum_i\sum_j a_i*a_j=(\sum a_i)^2\)
当然有另一个形式 \(\sum_i\sum_j a_i*a_j*[a_i!=a_j]=(\sum a_i)^2-\sum (a_i)^2\)
所以直接扫出边计算就行了。
主仆见证了 Hobo 的离别
考着考着忘记了 每个元件只会被融合一次。
只要可以建出来一个树,就可以发现,往上走必须全是 \(1\) , 往下走必须全是 \(0\) (可能反了,读者自推)。
然后预处理出来深度和根到他的权值和就可以了,注意为了线性复杂度可以考虑用 \(dfs\) 序判断祖先关系。
总结
第一次在下午考试,状态非常差。
一个半小时前两个打完拍,然后愣了一个小时啥也没干。
T3最后还是不会做,根本没想卡复杂度干干啥,其实你认为的 \(n^3\) 就可以A。
T4 最后很着急,忘了条件,所以根本不知道自己能不能想到建出来一个树。
总之状态很差,浪费了一套题。。。。。

浙公网安备 33010602011771号