zoukankan      html  css  js  c++  java
  • Note/Solution -「洛谷 P6466」分散层叠算法

    (mathcal{Description})

      Link.

      给定 (m) 个长度为 (n) 的有严格升序且不包含重复元素的序列 (a_1,a_2,cdots,a_m)(q) 个询问,每次询问给出 (x),求 (x) 在每个序列中的非严格后继的异或和。强制在线。

      (mle100)(nle10^4)(qle10^5)

    (mathcal{Solution})

      算是一种对多序列二分的优化科技/叭。

      思考两种暴力做法:

      第一种,直接在每个序列里二分求答案,则有单次 (mathcal O(mlog n))

      第二种,把 (m) 个序列归并为一个长度为 (nm) 的大序列,对于其每个位置记录其在原来 (m) 个序列中的非严格后继。则有 (mathcal O(nmlog m)-mathcal O(m+log(nm))),不过空间复杂度难以接受。

      而所谓“分散层叠算法”,就是对以上两种算法的平衡——假设我们求出了序列集 (b_1,b_2,cdots,b_m),其中 (b_1=a_1)(b_i~(i>1)) 是对 (a_1,a_2,cdots,a_i) 某种形式的“概括”,满足我们在 (b_i) 中二分 (x),能够找到 (x) 在实际 (a_i) 中的后继,同时找到 (x)(b_{i-1}) 中后继的近似位置,那么就能在 (mathcal O(1)) 调整该位置后迭代入 (b_{i-1}) 的子问题啦。

      具体地,构造 (b_i)

    [b_i=langle a_{i,1},a_{i,2},cdots,a_{i,n},b_{i-1,2},b_{i-1,4},cdots angle_{ ext{(sorted)}} ]

    即,(b_i)(a_i)(b_{i-1}) 的偶数位置元素构成的有序序列列。归纳可证,(b_i) 的长度不 过 (2n)。同时对于 (b_i) 中的每个元素,记录其在 (a_i) 中的后继位置以及其在 (b_{i-1})(完整的,包括奇数位置和偶数位置)中的后继位置(若不存在,设为最后一项,因为我们需要继续迭代调整)。

      预处理时间为 (mathcal O(nm)),结合上文查询方法,做到了 (mathcal O(nm)-mathcal O(log n+m))。这种 trick 常常与分块结合,可以加以扩展呢!

    (mathcal{Code})

      常数挺小的。(

    /* Clearink */
    
    #include <cstdio>
    #include <algorithm>
    
    #define rep( i, l, r ) for ( int i = l, repEnd##i = r; i <= repEnd##i; ++i )
    #define per( i, r, l ) for ( int i = r, repEnd##i = l; i >= repEnd##i; --i )
    
    inline char fgc() {
    	static char buf[1 << 17], *p = buf, *q = buf;
    	return p == q && ( q = buf + fread( p = buf, 1, 1 << 17, stdin ), p == q )
    		? EOF : *p++;
    }
    
    inline int rint() {
    	int x = 0, f = 1, s = fgc();
    	for ( ; s < '0' || '9' < s; s = fgc() ) f = s == '-' ? -f : f;
    	for ( ; '0' <= s && s <= '9'; s = fgc() ) x = x * 10 + ( s ^ '0' );
    	return x * f;
    }
    
    template<typename Tp>
    inline void wint( Tp x ) {
    	if ( x < 0 ) putchar( '-' ), x = -x;
    	if ( 9 < x ) wint( x / 10 );
    	putchar( x % 10 ^ '0' );
    }
    
    const int MAXN = 1e4, MAXM = 100;
    int n, m, q, D, a[MAXM + 5][MAXN + 5];
    
    int len[MAXM + 5], top[MAXN * 2 + 5];
    struct Atom { int val, nxa, nxb; };
    Atom b[MAXM + 5][MAXN * 2 + 5];
    
    inline void init() {
    	len[m] = n;
    	rep ( i, 1, n ) b[m][i] = { a[m][i], i, 0 };
    	static Atom tmp[MAXN + 5];
    	per ( i, m - 1, 1 ) {
    		int tlen = 0;
    		Atom* curb = b[i];
    		for ( int j = 2; j <= len[i + 1]; j += 2 ) {
    			tmp[++tlen] = { b[i + 1][j].val, 0, j };
    		}
    		int p = 1, q = 1;
    		rep ( j, 1, n ) {
    			for ( ; p <= tlen && tmp[p].val <= a[i][j]; ++p ) {
    				*++curb = tmp[p], curb->nxa = j;
    			}
    			for ( ; q < len[i + 1] && b[i + 1][q].val <= a[i][j]; ++q );
    			*++curb = { a[i][j], j, q };
    		}
    		for ( ; p <= tlen; *++curb = tmp[p++] );
    		len[i] = curb - b[i];
    		#ifdef RYBY
    			printf( "b[%d]:
    ", i );
    			rep ( j, 1, len[i] ) {
    				printf( "(%d,%d,%d) ", b[i][j].val, b[i][j].nxa, b[i][j].nxb );
    			}
    			putchar( '
    ' );
    		#endif
    	}
    	rep ( i, 1, len[1] ) top[i] = b[1][i].val;
    }
    
    int main() {
    	n = rint(), m = rint(), q = rint(), D = rint();
    	rep ( i, 1, m ) rep ( j, 1, n ) a[i][j] = rint();
    	init();
    	for ( int qid = 1, x, ans = 0; qid <= q; ++qid ) {
    		x = rint() ^ ans, ans = 0;
    		int p = std::lower_bound( top + 1, top + len[1] + 1, x ) - top;
    		ans ^= a[1][b[1][p].nxa];
    		#ifdef RYBY
    			printf( "in %d, p=%d: %d
    ", 1, p, a[1][b[1][p].nxa] );
    		#endif
    		rep ( i, 2, m ) {
    			p = b[i - 1][p].nxb;
    			for ( ; p < len[i] && b[i][p + 1].val <= x; ++p );
    			for ( ; p > 1 && b[i][p - 1].val >= x; --p );
    			#ifdef RYBY
    				printf( "in %d, p=%d: %d
    ", i, p, a[i][b[i][p].nxa] );
    			#endif
    			if ( a[i][b[i][p].nxa] >= x ) ans ^= a[i][b[i][p].nxa];
    		}
    		if ( !( qid % D ) ) wint( ans ), putchar( '
    ' );
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Delphi对接快递单的md5函数
    t+固定资产二维码打印工具2.01(支持微信查询)
    delphi 调用百度识别
    T+固定资产二维码卡片管理(外网版)
    Delphi 10.3.3 THTTPClient Post问题
    钉钉群机器人
    npm 命令集合
    php7的新特性
    ftp服务
    8.1 接口,接口也是一种类型
  • 原文地址:https://www.cnblogs.com/rainybunny/p/14655458.html
Copyright © 2011-2022 走看看