• 「Gym102956E」Brief Statements Union


    题目

    点这里看题目。

    分析

    我们用三元组 ((l,r,x)) 表示令 (a_l,a_{l+1},dots,a_r) 与起来为 (x) 的一条限制。

    考虑给定一堆限制的时候,如何检查它们合不合法。

    显然可以拆位考虑。枚举二进制的第 (k) 位,那么现在每个位置都只能是 0 或者 1。此时条件 ((l,r,x)) 会变成一下两种之一:

    1. 如果 (x) 在第 (k) 位上为 1,此时这个条件要求 (a_{l},a_{l+1},dots,a_r) 在第 (k) 位上与起来为 1,所以每个数必须都是 1;
    2. 如果 (x) 在第 (k) 位上位 0,此时这个条件要求 (a_l,a_{l+1},dots,a_r) 在第 (k) 位上与起来为 0,所以其中至少有一个 0;

    我们可以将所有的 1 限制先全部施加到序列上,再检查所有的 2 限制。既然可以检查了,我们就有了一个 (O(n^2log_2(max x))) 的算法。

    但是,虽然外层枚举的内容可以被化为若干个限制的区间,但是区间之间并没有良好的递推关系(因为这个检查方式是强制离线的)。注意到问题的要求是“不考虑某一条限制,其余限制能否同时成立”,因此,这导出了另一个方向:我们可以根据每一位上的检查情况,推断不考虑哪些限制可以保证剩余成立

    仍然枚举第 (k) 位,仍然先施加所有 1 限制。现在考虑 2 限制的冲突情况,假如有 (c) 条 2 限制出现了冲突:

    1. 如果 (c=0),那么当前位上任意删除一条限制都 OK;
    2. 如果 (c=1),那么我们删除冲突的那一条就 OK,但是删除其它的就不行;
    3. 如果 (c>1),怎么删除都不行;

    考虑完 2 限制的删除方式,我们接着考虑 1 限制的。2 限制的要求是“给定区间内有至少一个 0”,为了让某一冲突的限制的区间中出现 0,我们考虑区间中仅仅被覆盖了 1 次的位置,其中一个位置为 (i)。如果删除 (i) 所对应的区间,那么就可以让这条冲突的限制变得合法。

    那么对于一个 2 限制而言,我们需要做的是枚举其中所有仅被覆盖 1 次的位置,这些位置的 (g) 所对应的 1 限制就是删除后使得该 2 限制合法的所有 1 限制,我们不妨称为该 2 限制的“合法化 1 限制”。将所有的冲突的 2 限制的“合法化 1 限制”取交,我们得到的就是所有删除后可行的 1 限制。

    由于如下性质:对于仅仅被覆盖 1 次的位置 (i),设覆盖它的区间为 (g_i)。考虑三个仅被覆盖 1 次的位置 (i<j<k),如果有 (g_i=g_k),那么一定会有 (g_i=g_j=g_k)(这容易使用反证法说明);所以我们可以对于可能的“合法化 1 限制”重标号,使得 (g) 是单调的。那么每个冲突的 2 限制的“合法 1 限制”在重标号后,下标将会变成一段连续的区间,而区间取交是相当容易的。同时,由于 (g) 的单调性,寻找某个冲突的 2 限制的“合法 1 限制”区间也比较简单。

    精细实现后可以得到一个 (O(nlog_2(max a))) 的算法。

    小结:

    1. 一定要灵活转换思路,明知外层枚举的算法难以优化,就应该主动求变,舍弃掉这样的做法
    2. 思路不能僵化:对于“只忽略一条限制”的问题,不仅可以枚举,也可以推断
    3. 注意一下本题中利用标号的连续性质,将集合取交转化成区间取交的方法
    4. 注意一下实现细节:求 (g) 也可以使用差分。

    代码

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    
    #define rep( i, a, b ) for( int i = (a) ; i <= (b) ; i ++ )
    #define per( i, a, b ) for( int i = (a) ; i >= (b) ; i -- )
    
    typedef long long LL;
    
    const int MAXN = 1e6 + 5;
    
    template<typename _T>
    void read( _T &x )
    {
    	x = 0; char s = getchar(); int f = 1;
    	while( ! ( '0' <= s && s <= '9' ) ) { f = 1; if( s == '-' ) f = -1; s = getchar(); }
    	while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar(); }
    	x *= f;
    }
    
    template<typename _T>
    void write( _T x )
    {
    	if( x < 0 ) putchar( '-' ), x = -x;
    	if( 9 < x ) write( x / 10 );
    	putchar( x % 10 + '0' );
    }
    
    int vio[MAXN], tot;
    int pos[MAXN], seq[MAXN], ID;
    
    LL f[MAXN], g[MAXN];
    int nxt[MAXN], pre[MAXN];
    
    int ans[MAXN];
    
    int qL[MAXN], qR[MAXN]; LL qX[MAXN];
    int N, K;
    
    int main()
    {
    	read( N ), read( K );
    	rep( i, 1, K ) read( qL[i] ), read( qR[i] ), read( qX[i] );
    	nxt[N + 1] = N + 1, pre[0] = 0;
    	for( int k = 0 ; k < 60 ; k ++ )
    	{
    		rep( i, 1, N ) f[i] = g[i] = 0;
    		rep( i, 1, K )
    			if( qX[i] >> k & 1 )
    			{
    				f[qL[i]] ++, f[qR[i] + 1] --;
    				g[qL[i]] += i, g[qR[i] + 1] -= i;
    			}
    		rep( i, 1, N ) f[i] += f[i - 1], g[i] += g[i - 1];
    		per( i, N, 1 ) nxt[i] = f[i] ? nxt[i + 1] : i;
    		ID = tot = 0;
    		rep( i, 1, K )
    			if( ! ( qX[i] >> k & 1 ) )
    				if( nxt[qL[i]] > qR[i] )
    					vio[++ tot] = i;
    		if( tot == 0 )
    		{
    			rep( i, 1, K ) ans[i] ++;
    			continue;
    		}
    		if( tot == 1 ) ans[vio[1]] ++;
    		rep( i, 1, N ) 
    			if( f[i] == 1 && ! pos[g[i]] )
    				seq[pos[g[i]] = ++ ID] = g[i];
    		rep( i, 1, N ) pre[i] = f[i] == 1 ? i : pre[i - 1];
    		per( i, N, 1 ) nxt[i] = f[i] == 1 ? i : nxt[i + 1];
    		int l = 0, r = ID;
    		rep( i, 1, tot )
    		{
    			int u = vio[i];
    			if( nxt[qL[u]] <= qR[u] )
    				l = std :: max( l, pos[g[nxt[qL[u]]]] );
    			else
    				l = ID + 1;
    			if( pre[qR[u]] >= qL[u] )
    				r = std :: min( r, pos[g[pre[qR[u]]]] );
    			else
    				r = 0;
    		}
    		rep( i, l, r ) ans[seq[i]] ++;
    		rep( i, 1, K ) pos[i] = 0;
    	}
    	rep( i, 1, K ) putchar( ( ans[i] == 60 ) + '0' );
    	puts( "" );
    	return 0;
    }
    
  • 相关阅读:
    Android中onBackPressed()的使用
    Python初次学习
    svn Mac下面无法更新png
    UIView的layoutSubviews和drawRect
    "_deflate", referenced from: -[NSData(NSDataAdditions) gzipDeflate] in NSDataAdditions.o
    Error12
    pods安装
    xib为view添加边框
    这些机型将被淘汰
    Development cannot be enabled while your device is locked.
  • 原文地址:https://www.cnblogs.com/crashed/p/15173016.html
Copyright © 2020-2023  润新知