• Solution -「CF 1392G」Omkar and Pies


    (mathcal{Description})

      Link.

      给定两个长度为 (K)(01)(S,T)(n) 组操作 ((a_i,b_i)),意义为交换 (S_{a_i})(S_{b_i})。你需要执行一段长度不小于 (m) 的连续操作区间,最大化 (S)(T) 相同的位数。求出最大相同位数。

      (Kle20)(mle nle10^6)

    (mathcal{Solution})

      一个简单的性质:(S)(T) 同时执行相同操作,答案不变。

      那么可以想到利用后缀和——记 (S_i) 表示 (S) 依次执行操作 (isim n) 所得到的串,(T_i) 同理。根据性质,(S) 操作区间 ([l,r]) 后与 (T) 的相同位数等于 (S_l)(T_{r+1}) 的相同位数。

      现在问题变成,给定两个长为 (n+1) 的串序列 ({S_{n+1}},{T_{n+1}}),求:

    [ max_{1le i+m-1le rle n+1}{operatorname{same}(S_i,T_j)} ]

      其中 (operatorname{same}) 表示两个串的相同位数。

      接下来考虑 DP。定义:

    [ f(0,v)=min_{vin S_i}i\ f(1,v)=max_{vin T_i}i ]

      枚举二进制 (v),转移,如果有 (f(0,v)+m-1le f(1,v)),就可以用 (operatorname{popcount}(v)) 更新答案。

    (mathcal{Code})

    /* Clearink */
    
    #include <cstdio>
    
    inline int rint ( const int base = 10 ) {
    	int x = 0; char s = getchar ();
    	for ( ; s < '0' || '9' < s; s = getchar () );
    	for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * base + ( s ^ '0' );
    	return x;
    }
    
    template<typename Tp>
    inline void wint ( Tp x ) {
    	if ( x < 0 ) putchar ( '-' ), x = ~ x + 1;
    	if ( 9 < x ) wint ( x / 10 );
    	putchar ( x % 10 ^ '0' );
    }
    
    inline void chkmin ( int& a, const int b ) { b < a ? a = b : 0; }
    inline void chkmax ( int& a, const int b ) { a < b ? a = b : 0; }
    
    const int MAXN = 1e6, MAXS = 1 << 20;
    int n, m, S, T, K, a[MAXN + 5], b[MAXN + 5], p[MAXN + 5], f[2][MAXS | 5];
    
    inline int swp ( int x ) {
    	int ret = 0;
    	for ( int i = 0; i < K; ++ i ) ret |= ( ( x >> i ) & 1 ) << p[i];
    	return ret;
    }
    
    int main () {
    	n = rint (), m = rint (), K = rint ();
    	S = rint ( 2 ), T = rint ( 2 );
    	for ( int i = 1; i <= n; ++ i ) a[i] = K - rint (), b[i] = K - rint ();
    	for ( int s = 0; s < 1 << K; ++ s ) f[0][s] = n + 1, f[1][s] = -1;
    	f[1][T] = n + 1;
    	for ( int i = 0; i < K; ++ i ) p[i] = i;
    	for ( int i = n; i; -- i ) {
    		p[a[i]] ^= p[b[i]] ^= p[a[i]] ^= p[b[i]];
    		chkmin ( f[0][swp ( S )], i ), chkmax ( f[1][swp ( T )], i );
    	}
    	int ans = -1, ansl = -1, ansr = -1;
    	for ( int s = ( 1 << K ) - 1; ~s; -- s ) {
    		for ( int i = 0; i < K; ++ i ) {
    			if ( !( ( s >> i ) & 1 ) ) continue;
    			chkmin ( f[0][s ^ ( 1 << i )], f[0][s] );
    			chkmax ( f[1][s ^ ( 1 << i )], f[1][s] );
    		}
    		if ( f[1][s] - f[0][s] >= m ) {
    			if ( int t = __builtin_popcount ( s ); ans < t ) {
    				ans = t, ansl = f[0][s], ansr = f[1][s] - 1;
    			}
    		}
    	}
    	ans = 2 * ans + K - __builtin_popcount ( S ) - __builtin_popcount ( T );
    	wint ( ans ), putchar ( '
    ' );
    	wint ( ansl ), putchar ( ' ' ), wint ( ansr ), putchar ( '
    ' );
    	return 0;
    }
    
  • 相关阅读:
    ACM题目————食物链
    ACM题目————Find them, Catch them
    hdu 1255 覆盖的面积 (线段树处理面积覆盖问题(模板))
    poj 3373 Changing Digits (DFS + 记忆化剪枝+鸽巢原理思想)
    hdu 3303 Harmony Forever (线段树 + 抽屉原理)
    hdu 2665 Kth number(划分树模板)
    poj 1348 Computing (四个数的加减乘除四则运算)
    hdu 1021 Fibonacci Again(找规律)
    HDU 1560 DNA sequence (IDA* 迭代加深 搜索)
    hdu 1560 DNA sequence(搜索)
  • 原文地址:https://www.cnblogs.com/rainybunny/p/13734638.html
Copyright © 2020-2023  润新知