• [TJOI2017]异或和


    题目

    点这里看题目。

    分析

    显然要先计算前缀和(s)

    同样地考虑按位计算贡献。假设当前枚举到了第(k)位,正在枚举第(i)个前缀和,设(x)的第(k)位为(b(x)),后(k-1)位为(l(x))。由于子区间和就是前缀和做差,我们就考虑什么情况下,前缀和(i)做差后在(k)位上为 1 。

    (b(s_i)=0),那么减数(t)需要满足:若(b(t)=1),则(l(t)<l(x)),得到差的 1 ;若(b(t)=0),则(l(t)>l(x)),得到退位的 1 。

    (b(s_i)=1),那么减数(t)需要满足:若(b(t)=1),则(l(t)>l(x)),得到退位的 1 ;若(b(t)),则(l(t)<l(x)),得到差的 1 。

    发现有贡献的情况对应了值域上的一段区间,因此我们可以用 BIT 维护区间和。时间(O(nlog_2nlog_2sum a))

    代码

    #include <cstdio>
    #include <cstring>
    
    const int MAXN = 1e5 + 5, MAXA = 1e6 + 5;
    
    template<typename _T>
    void read( _T &x )
    {
    	x = 0;char s = getchar();int f = 1;
    	while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
    	while( s >= '0' && 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 ) + 1; }
    	if( 9 < x ){ write( x / 10 ); }
    	putchar( x % 10 + '0' );
    }
    
    template<typename _T>
    _T MAX( const _T a, const _T b )
    {
    	return a > b ? a : b;
    }
    
    template<typename _T>
    void swapp( _T &x, _T &y )
    {
    	_T t( x ); x = y, y = t;
    }
    
    int a[MAXN], s[MAXN];
    int N, all;
    
    struct PreSum
    {
    	int BIT[MAXA];
    	
    	PreSum() { memset( BIT, 0, sizeof BIT ); }
    	void up( int &x ) const { x += x & ( -x ); }
    	void down( int &x ) const { x -= x & ( -x ); }
    	void update( int x, const int v ) { for( ; x <= all ; up( x ) ) BIT[x] += v; }
    	int getSum( int x ) const { int ret = 0; for( ; x ; down( x ) ) ret += BIT[x]; return ret; }
    	
    	int operator () ( const int l, const int r ) const 
    	{ 
    		if( l > r ) return 0;
    		int tr = getSum( r ), tl = getSum( l - 1 );
    		return tr - tl;
    	}
    }One, Zero;
    
    int main()
    {
    	read( N );
    	int ans = 0, cnt, bit, low;
    	for( int i = 1 ; i <= N ; i ++ ) read( a[i] ), all += a[i];
    	for( int i = 1 ; i <= N ; i ++ ) s[i] = s[i - 1] + a[i];
    	Zero.update( 1, 1 );
    	for( int k = 1 ; k <= all ; k <<= 1 )
    	{
    		cnt = 0;
    		for( int i = 1 ; i <= N ; i ++ )
    		{
    			bit = bool( s[i] & k ), low = s[i] & ( k - 1 );
    			if( bit ) cnt += Zero( 1, low + 1 ), cnt += One( low + 2, k );
    			else cnt += Zero( low + 2, k ), cnt += One( 1, low + 1 );
    			if( bit ) One.update( low + 1, 1 );
    			else Zero.update( low + 1, 1 );
    			cnt &= 1;
    		}
    		if( cnt ) ans |= k;
    		for( int i = 1 ; i <= N ; i ++ )
    		{
    			bit = bool( s[i] & k ), low = s[i] & ( k - 1 );
    			if( bit ) One.update( low + 1, -1 );
    			else Zero.update( low + 1, -1 );
    		}
    	}
    	write( ans ), putchar( '
    ' );
    	return 0;
    }
    
  • 相关阅读:
    java的map
    linux的date的几个例子
    URI记录
    eclipse进行关联代码
    hive的top n
    python类定义
    sql一些常用的经典语句,最后是select as的用法
    linux,shell脚本set -x的意思
    python循环for,range,xrange;while
    python安装json的方法;以及三种json库的区别
  • 原文地址:https://www.cnblogs.com/crashed/p/13122146.html
Copyright © 2020-2023  润新知