bzoj 2038 小z的袜子 莫队例题
2015-02-22 14:30
197 查看
莫队,利用可以快速地通过一个问题的答案得到另一问题的答案这一特性,合理地组织问题的求解顺序,将已解决的问题帮助解决当前问题,来优化时间复杂度。
典型用法:处理静态(无修改)离线区间查询问题。
线段树也是处理区间问题的一个有力工具,它和莫队算法各有特点:
线段树可以支持修改,并且单次操作时间复杂度一般为O(log),支持在线,但是要求可以进行快速的区间合并操作,两个区间如不能快速合并(f(n)*O(log)>O(n)),则用线段树就没有什么实际价值了(暴力都比它块)
莫队算法可以解决某些线段树不能解决的静态离线问题,但它要求可以快速地从一个答案得到另一个答案。
对于区间问题,假如我们得到了区间[l,r]的答案,能通过它用O(1)的时间得到[l-1,r],[l+1,r],[l,r-1],[l,r+1]的答案,那么我们将[l,r]看成二维平面上的点,两个点的距离用哈密顿距离表示,一个不错的想法是找到图的最小生成树,然后暴力推出一个点,其它点从它延伸过去就行了,时间复杂度是距离和加上暴力的那个点花的时间。
这道题除了上面的做法,还可以分块,如果分成n^0.5块,可以做到O(n^1.5)的复杂度。
做法是先将原颜色序列分成根号n块,然后将询问先按左端点排序,对于每一块的询问再按右端点排序(都是升序)。
每次计算一个左端点在一个块中的询问,先暴力这个区间的第一个询问,然后后面的每个询问从它前一个询问推(具体看代码)
时间复杂度可以这么看:
排序O(nlogn)
对于每个询问,它从前一个推过来,因为它们在同一块中,前端点改变最多O(n^0.5)次,有O(n)个询问,所以前端点变化O(n*n^0.5)次
对于每一段,后端点变化是O(n)的,而最多有O(n^0.5)段,所以后端点变化O(n^0.5*n)次
所以从一个[l,r]推到它四个相邻的点的次数是O(n^1.5),而转移是O(1)的,所以总的复杂度是O(n^1.5)。
不论是分块还是最小生成树,都是想用最少的转移和最少的暴力将所有询问解决。
不会写最小生成树的做法。这个是分块,感谢proverbs
View Code
典型用法:处理静态(无修改)离线区间查询问题。
线段树也是处理区间问题的一个有力工具,它和莫队算法各有特点:
线段树可以支持修改,并且单次操作时间复杂度一般为O(log),支持在线,但是要求可以进行快速的区间合并操作,两个区间如不能快速合并(f(n)*O(log)>O(n)),则用线段树就没有什么实际价值了(暴力都比它块)
莫队算法可以解决某些线段树不能解决的静态离线问题,但它要求可以快速地从一个答案得到另一个答案。
对于区间问题,假如我们得到了区间[l,r]的答案,能通过它用O(1)的时间得到[l-1,r],[l+1,r],[l,r-1],[l,r+1]的答案,那么我们将[l,r]看成二维平面上的点,两个点的距离用哈密顿距离表示,一个不错的想法是找到图的最小生成树,然后暴力推出一个点,其它点从它延伸过去就行了,时间复杂度是距离和加上暴力的那个点花的时间。
这道题除了上面的做法,还可以分块,如果分成n^0.5块,可以做到O(n^1.5)的复杂度。
做法是先将原颜色序列分成根号n块,然后将询问先按左端点排序,对于每一块的询问再按右端点排序(都是升序)。
每次计算一个左端点在一个块中的询问,先暴力这个区间的第一个询问,然后后面的每个询问从它前一个询问推(具体看代码)
时间复杂度可以这么看:
排序O(nlogn)
对于每个询问,它从前一个推过来,因为它们在同一块中,前端点改变最多O(n^0.5)次,有O(n)个询问,所以前端点变化O(n*n^0.5)次
对于每一段,后端点变化是O(n)的,而最多有O(n^0.5)段,所以后端点变化O(n^0.5*n)次
所以从一个[l,r]推到它四个相邻的点的次数是O(n^1.5),而转移是O(1)的,所以总的复杂度是O(n^1.5)。
不论是分块还是最小生成树,都是想用最少的转移和最少的暴力将所有询问解决。
不会写最小生成树的做法。这个是分块,感谢proverbs
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define maxn 100010 using namespace std; typedef long long lng; struct Qu { int l, r, id; }; bool cmpl( const Qu & a, const Qu & b ) { return a.l < b.l; } bool cmpr( const Qu & a, const Qu & b ) { return a.r < b.r; } int n, m; int idx[maxn], itot; int clr[maxn]; lng cnt[maxn]; int lx[maxn], rx[maxn], stot; Qu qu[maxn]; lng ans[maxn]; void partition() { int len = (int)ceil(sqrt(n)); stot = n/len; rx[0] = 0; for( int i=1; i<=stot; i++ ) { lx[i] = rx[i-1]+1; rx[i] = rx[i-1]+len; } if( rx[stot]!=n ) { stot++; lx[stot] = rx[stot-1]+1; rx[stot] = n; } } void makeid() { sort( idx+1, idx+1+n ); int tot = unique( idx+1, idx+1+n ) - idx; for( int i=1; i<=n; i++ ) clr[i] = lower_bound( idx+1, idx+tot, clr[i] ) - idx; } lng cube( lng a ) { return a*a*a; } void update( lng &sum, int c, int delta ) { sum -= cube(cnt[c]); cnt[c] += delta; sum += cube(cnt[c]); } void work() { sort( qu+1, qu+1+m, cmpl ); for( int i=1,s=1,t=1; i<=stot; i++ ) { memset( cnt, 0, sizeof(cnt) ); while( s<=m && qu[s].l<lx[i] ) s++; while( t<=m && qu[t].l<=rx[i] ) t++; sort( qu+s, qu+t, cmpr ); lng sum = 0; for( int j=qu[s].l; j<=qu[s].r; j++ ) update( sum, clr[j], +1 ); ans[qu[s].id] = sum; for( int q=s+1; q<t; q++ ) { if( qu[q].l<=qu[q-1].l ) { // [ ( ) ] for( int j=qu[q].l; j<qu[q-1].l; j++ ) update( sum, clr[j], +1 ); for( int j=qu[q-1].r+1; j<=qu[q].r; j++ ) update( sum, clr[j], +1 ); } else if( qu[q].l>qu[q-1].r ) { // ( ) [ ] for( int j=qu[q-1].l; j<=qu[q-1].r; j++ ) cnt[clr[j]]--; sum = 0; for( int j=qu[q].l; j<=qu[q].r; j++ ) update( sum, clr[j], +1 ); } else { // ( [ ) ] for( int j=qu[q-1].l; j<qu[q].l; j++ ) update( sum, clr[j], -1 ); for( int j=qu[q-1].r+1; j<=qu[q].r; j++ ) update( sum, clr[j], +1 ); } ans[qu[q].id] = sum; } } } int main() { scanf( "%d", &n ); for( int i=1; i<=n; i++ ) { scanf( "%d", idx+i ); clr[i] = idx[i]; } scanf( "%d", &m ); for( int i=1; i<=m; i++ ) { scanf( "%d%d", &qu[i].l, &qu[i].r ); qu[i].id = i; } makeid(); partition(); work(); for( int i=1; i<=m; i++ ) printf( "%lld\n", ans[i] ); }
View Code
相关文章推荐
- BZOJ 2038: [2009国家集训队]小Z的袜子(莫队算法例题)
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)(莫队算法)
- 【BZOJ 2038】小Z的袜子&莫队算法详解
- bzoj 2038: [2009国家集训队]小Z的袜子(hose) 【莫队算法】
- BZOJ 2038 小Z的袜子(hose) [莫队算法]
- BZOJ-2038-小Z的袜子hose-莫队
- BZOJ 2038 小Z的袜子(hose) 莫队
- [bzoj]2038: [2009国家集训队]美妙的袜子!(莫队)
- [国家集训队][bzoj2038] 小Z的袜子 [莫队]
- BZOJ 2038 小Z的袜子(hose) 莫队算法
- bzoj 2038 小Z的袜子(莫队)
- BZOJ - 2038: 小Z的袜子(hose) 莫队算法 模板
- BZOJ 2038 小Z的袜子 莫队算法(模板题)
- bzoj 2038 小Z的袜子 莫队模板
- 莫队(bzoj 2038: [2009国家集训队]小Z的袜子(hose))
- 小Z的袜子(hose) - bzoj 2038 莫队算法
- 【BZOJ】2038 [2009国家集训队]小Z的袜子(hose) 莫队
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)&&莫队算法
- [BZOJ 2038] 2009国家集训队 小Z的袜子 · 莫队算法
- [BZOJ 2038]小Z的袜子 莫队(Mo's Algorithm)模板题