[JOISC2014]歴史の研究/[BZOJ4241]历史研究
2018-08-19 19:39
417 查看
[JOISC2014]歴史の研究/[BZOJ4241]历史研究
题目大意:
一个长度为\(n(n\le10^5)\)的数列\(A(A_i\le10^9)\),定义一个元素对一个区间\([l,r]\)的贡献为\(A_i\times cnt(A_i)\),其中\(cnt(A_i)\)表示\(A_i\)在区间内的出现次数。\(q(q\le10^5)\)次询问,每次询问一个区间内贡献最大的元素的贡献。
思路:
分块。
\(cnt[i][j]\)表示前\(i\)块内\(j\)的出现次数,\(sum[i][j]\)表示\([begin(i),end(j)]\)的答案。
对\(A\)离散化后预处理\(cnt\)和\(sum\),询问时如果\(l,r\)在同一块直接暴力。如果不在同一块,则答案要么是\(sum[bel(l)+1,bel(r)-1]\),要么是\(l,r\)所在块中出现过的元素的贡献。
时间复杂度\(\mathcal O(n^{\frac32})\)。
源代码:
#include<cmath> #include<cstdio> #include<cctype> #include<algorithm> inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } typedef long long int64; const int N=1e5,M=317; int n,m,q,block,a ,b ,bel ,begin[M],end[M],tmp ,cnt[M] ; int64 sum[M][M]; inline int64 query(const int &l,const int &r) { int64 ret=0; if(bel[l]==bel[r]) { for(register int i=l;i<=r;i++) { tmp[a[i]]++; ret=std::max(ret,(int64)b[a[i]]*tmp[a[i]]); } for(register int i=l;i<=r;i++) tmp[a[i]]--; return ret; } ret=sum[bel[l]+1][bel[r]-1]; for(register int i=l;i<=end[bel[l]];i++) { tmp[a[i]]++; ret=std::max(ret,(int64)b[a[i]]*(tmp[a[i]]+cnt[bel[r]-1][a[i]]-cnt[bel[l]][a[i]])); } for(register int i=begin[bel[r]];i<=r;i++) { tmp[a[i]]++; ret=std::max(ret,(int64)b[a[i]]*(tmp[a[i]]+cnt[bel[r]-1][a[i]]-cnt[bel[l]][a[i]])); } for(register int i=l;i<=end[bel[l]];i++) tmp[a[i]]--; for(register int i=begin[bel[r]];i<=r;i++) tmp[a[i]]--; return ret; } int main() { n=getint(),q=getint(),block=sqrt(n); for(register int i=0;i<n;i++) { a[i]=b[i]=getint(); bel[i]=i/block; end[bel[i]]=i; } for(register int i=n-1;i>=0;i--) { begin[bel[i]]=i; } std::sort(&b[0],&b ); m=std::unique(&b[0],&b )-b; for(register int i=0;i<n;i++) { a[i]=std::lower_bound(&b[0],&b[m],a[i])-b; cnt[bel[i]][a[i]]++; } for(register int i=1;i<=bel[n-1];i++) { for(register int j=0;j<m;j++) { cnt[i][j]+=cnt[i-1][j]; } } for(register int i=0;i<=bel[n-1];i++) { for(register int j=begin[i];j<=end[i];j++) { tmp[a[j]]++; sum[i][i]=std::max(sum[i][i],(int64)b[a[j]]*tmp[a[j]]); } for(register int j=begin[i];j<=end[i];j++) tmp[a[j]]--; for(register int j=i+1;j<=bel[n-1];j++) { sum[i][j]=sum[i][j-1]; for(register int k=begin[j];k<=end[j];k++) { tmp[a[k]]++; sum[i][j]=std::max(sum[i][j],(int64)b[a[k]]*(tmp[a[k]]+cnt[j-1][a[k]]-(i!=0?cnt[i-1][a[k]]:0))); } for(register int k=begin[j];k<=end[j];k++) tmp[a[k]]--; } } for(register int i=0;i<q;i++) { const int l=getint()-1,r=getint()-1; printf("%lld\n",query(l,r)); } return 0; }
相关文章推荐
- BZOJ 4241: 历史研究
- [分块] BZOJ 4241 历史研究
- bzoj4241 历史研究
- [bzoj4241]历史研究
- bzoj:4241: 历史研究
- 【bzoj4241】历史研究 分块
- [bzoj 4241]历史研究
- [BZOJ]4241 历史研究 回滚莫队
- BZOJ 4241 历史研究 (回滚莫队)
- bzoj 4241: 历史研究 分块
- bzoj 4241: 历史研究
- 【BZOJ4241】历史研究 分块
- 【bzoj4241】 历史研究
- BZOJ4241 历史研究
- [bzoj4241]历史研究 回滚莫队
- BZOJ 4241: 历史研究——莫队 二叉堆
- 【bzoj4241】历史研究 分块
- bzoj4241 历史研究
- [BZOJ4241]-历史研究-回滚莫队
- 【BZOJ4241】【回滚莫队】历史研究 (非题解的学习分析)