zoukankan      html  css  js  c++  java
  • Solution -「COCI 2014-2015 #2」「洛谷 P6406」Norma

    (mathcal{Description})

      Link.

      给定 ({a_n}),求:

    [sum_{i=1}^nsum_{j=i}^n(j-i+1)min_{k=i}^j{a_k}max_{k=i}^j{a_k} ]

      答案对 (10^9) 取模。

    (mathcal{Solution})

      挺可爱的一道题 w。

      静态序列计数问题,可以考虑分治:对于 ([l,r])(l<r)),令分割点 (p=lfloorfrac{l+r}2 floor),对满足左端点在 ([l,p]),右端点在 ((p,r]) 的区间进行计算,然后递归两个区间继续求解。

      对于本题,可以枚举区间左端点 (i=p,p-1,cdots,l),记 (s=min_{u=i}^p{a_u})(t=max_{u=i}^p{a_u})(j=max_{uin(p,r]}{u|min_{v=i}^j{a_v}=s})(k=max_{uin(p,r]}{u|max_{v=i}^j{a_v}=t}),只讨论 (jle k),发现对于将要计数的区间 ([i,x]),分三种情况:

    • (xin(p,j]):最小值、最大值都在 ([l,p]) 中取到,那么只需要关心 (x) 的位置,故此情况对答案的贡献为:

      [pqsum_{xin(p,j]}(x-i+1) ]

    • (xin(j,k]):最大值在 ([l,p]) 中取到,而最小值会在 ((p,x]) 中取到,则要求:

      [qsum_{xin(j,k]}(x-i+1)min_{u=p+1}^x{a_u} ]

      求和内是一个距离 ( imes) 权值的形式,尝试预处理出值的前缀和和下标 ( imes) 值的前缀和,就能 (mathcal O(1)) 计算了,这里略过,详见代码。

    • (xin(k,r]):最小值、最大值都在 ((p,x]) 中取到,类似地求:

      [sum_{xin(k,r]}(x-i+1)min_{u=p+1}^x{a_u}max_{u=p+1}^x{a_u} ]

      仍然预处理出两种前缀和,(mathcal O(1)) 计算。

      综上,在分治的 (mathcal O(nlog n)) 的时间内解决本题。

    (mathcal{Code})

    /* Clearink */
    
    #include <cstdio>
    
    inline int rint () {
    	int x = 0; char s = getchar ();
    	for ( ; s < '0' || '9' < s; s = getchar () );
    	for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
    	return x;
    }
    
    const int MAXN = 5e5, MOD = 1e9;
    int n, a[MAXN + 5], ans;
    int smx[MAXN + 5], vmx[MAXN + 5];
    int smn[MAXN + 5], vmn[MAXN + 5];
    int sxn[MAXN + 5], vxn[MAXN + 5];
    
    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 ); }
    inline int mul ( const long long a, const int b ) { return a * b % MOD; }
    inline int sub ( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
    inline int add ( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
    inline void addeq ( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD, 0 ); }
    inline int sum ( const int l, const int r ) {
    	return r < l ? 0 : ( ( l + r ) * ( r - l + 1ll ) >> 1 ) % MOD;
    }
    
    inline void solve ( const int l, const int r ) {
    	if ( l == r ) return addeq ( ans, mul ( a[l], a[l] ) );
    	int mid = l + r >> 1;
    	smx[mid] = vmx[mid] = smn[mid] = vmn[mid] = sxn[mid] = vxn[mid] = 0;
    	for ( int i = mid + 1, mn = a[mid + 1], mx = a[mid + 1];
    		i <= r; ++i, chkmin ( mn, a[i] ), chkmax ( mx, a[i] ) ) {
    		vmx[i] = add ( vmx[i - 1], mx ),
    		smx[i] = add ( smx[i - 1], mul ( i - mid, mx ) );
    		vmn[i] = add ( vmn[i - 1], mn ),
    		smn[i] = add ( smn[i - 1], mul ( i - mid, mn ) );
    		vxn[i] = add ( vxn[i - 1], mul ( mn, mx ) ),
    		sxn[i] = add ( sxn[i - 1], mul ( i - mid, mul ( mn, mx ) ) );
    	}
    	for ( int i = mid, mn = a[i], mx = a[i], j = mid + 1, k = mid + 1;
    		i >= l; --i, chkmin ( mn, a[i] ), chkmax ( mx, a[i] ) ) {
    		for ( ; j <= r && mn <= a[j]; ++j );
    		for ( ; k <= r && a[k] <= mx; ++k );
    		int p = j < k ? j : k, q = j ^ k ^ p; // [mid+1,p),[p,q),[q,r].
    		addeq ( ans, mul ( mul ( mn, mx ), sum ( mid + 2 - i, p - i ) ) );
    		if ( j <= k ) { // max is constant while min will change.
    			addeq ( ans, mul ( mx, add (
    				mul ( mid - i + 1, sub ( vmn[k - 1], vmn[j - 1] ) ),
    				sub ( smn[k - 1], smn[j - 1] ) ) ) );
    		} else { // min is constant while max will change.
    			addeq ( ans, mul ( mn, add (
    				mul ( mid - i + 1, sub ( vmx[j - 1], vmx[k - 1] ) ),
    				sub ( smx[j - 1], smx[k - 1] ) ) ) );
    		}
    		addeq ( ans, add (
    			mul ( mid - i + 1, sub ( vxn[r], vxn[q - 1] ) ),
    			sub ( sxn[r], sxn[q - 1] ) ) );
    	}
    	solve ( l, mid ), solve ( mid + 1, r );
    }
    
    int main () {
    	n = rint ();
    	for ( int i = 1; i <= n; ++i ) a[i] = rint ();
    	solve ( 1, n );
    	printf ( "%d
    ", ans );
    	return 0;
    }
    
  • 相关阅读:
    开放平台整理
    Ubuntu Linux之软件源 解释
    遇到的几个linux问题,顺便把网上查到的帖过来
    Linux之网络配置
    Linux维护之Grub应用与问题汇总
    Linux维护之我用过的命令汇总(没多少意义,给我自己看的)
    大数据hadoop目录
    大数据hadoop环境搭建伪分布式模式
    大数据数据分析numpy库数组创建方式、数组的数据类型
    大数据hadoop运行模式
  • 原文地址:https://www.cnblogs.com/rainybunny/p/14124401.html
Copyright © 2011-2022 走看看