zoukankan      html  css  js  c++  java
  • 【UR #17】滑稽树上滑稽果

    A 【UR #17】滑稽树上滑稽果 [* easy]

    给定 (n) 个数 (a_i),将他们排成一棵树,定义 (i) 的权值为 (i) 到链顶的点权的 (mathbf{and}) 的值。

    求最小权值和。

    (nle 10^5,a_ile 2 imes 10^5)

    Solution

    显然最优解是变成链,而且通过不超过 (log w) 个元素就可以变成所有元素的 (mathbf{and}) 值。

    可以认为问题等价于现在有全集,使用 (i) 个元素,将其缩小到 (mathbf{and}) 和的最小花费。

    然后答案就是 (f_{i}+(n-i) imes {mathbf{and}})

    考虑计算 (f_{i,S}) 表示用了 (i) 个元素,(mathbf{and})(S) 的最优解((ile log w)

    于是得到了一个 (mathcal O(nwlog w)) 的做法。

    考虑优化,我们发现 (S) 只会从大的转移到小的,将 (i) 这个维度压掉,然后从大到小转移。

    枚举 (S) 的子集 (T) 这样 (S o T) 当且仅当存在一个元素为 ((Tland S)land U) 的子集,显然如果存在那么 (S) 可以去往更小的 (T),在此 (T) 处更新答案不会使得答案更劣。

    那么从小到大预处理一次,然后再从大往小 dp 一边即可。

    复杂度为 (mathcal O(3^{18}))

    (Code:)

    #include<bits/stdc++.h>
    using namespace std ;
    #define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
    #define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
    #define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
    #define re register
    int gi() {
    	char cc = getchar() ; int cn = 0, flus = 1 ;
    	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
    	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
    	return cn * flus ;
    }
    const int Inf = 1e15 ; 
    const int N = (1 << 18) + 5 ; 
    int n, limit, A, a[N], w[N] ;
    long long f[N] ; 
    signed main()
    {
    	n = gi(), limit = (1 << 18) - 1 ; 
    	rep( i, 1, n ) a[i] = gi(), w[a[i]] = 1 ; 
    	A = a[1] ;
    	rep( i, 2, n ) A &= a[i] ; 
    	memset( f, 63, sizeof(f) ) ; 
    	rep( i, 1, n ) f[a[i]] = 1ll * a[i] + 1ll * (n - 1) * A ; 
    	rep( j, 1, limit ) for(re int k = 1; k <= limit; k <<= 1)
    		if(j & k) w[j] |= w[j ^ k] ; 
    	drep( S, 0, limit ) {
    		if( f[S] > Inf ) continue ; 
    		for(re int i = S; ; i = ((i - 1) & S) ) {
    			int u = (i | (S ^ limit) ) ; 
    			if( w[u] ) f[i] = min( f[i], f[S] + (i - A) ) ;
    			if( !i ) break ; 
    		}
    	}
    	cout << f[A] << endl ; 
    	return 0 ;
    }
    
  • 相关阅读:
    Linux 下杀毒可用工具 clamav
    Docker 添加环境系统文件配置
    Docker 空间大小设置
    Docker 扩容 容器空间大小
    bzoj 1088 DP
    bzoj 1096 斜率优化DP
    spoj p104 Matrix-Tree定理
    bzoj 1016 深搜
    WC后记
    bzoj 1301 后缀数组
  • 原文地址:https://www.cnblogs.com/Soulist/p/13881880.html
Copyright © 2011-2022 走看看