bzoj 3781 小B的询问——分块
Posted narh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3781 小B的询问——分块相关的知识,希望对你有一定的参考价值。
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3781
非常经典的分块套路。于是时间空间比大家的莫队差了好多……
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define ll long long using namespace std; const int N=5e4+5,M=230; int n,m,w,base,a[N],cnt[M][N],ct[N]; ll sm[M][M],ans; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)fx=0;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘) ret=(ret<<3)+(ret<<1)+ch-‘0‘,ch=getchar(); return fx?ret:-ret; } int bh(int a){return (a-1)/base+1;} void init() { int R=bh(n); for(int i=1;i<=R;i++) { int t=i*base,j=i; if(t>n) { t=(i-1)*base; for(int k=t+1;k<=n;k++) sm[i][i]+=(cnt[i][a[k]]<<1)+1,cnt[i][a[k]]++; j=i-1; } for(;t;j--) { sm[i][j]+=sm[i][j+1];// for(int k=1;k<=base;k++,t--) { sm[i][j]+=(cnt[i][a[t]]<<1)+1; cnt[i][a[t]]++; } } } } int main() { n=rdn(); m=rdn(); w=rdn(); base=sqrt(n); for(int i=1;i<=n;i++)a[i]=rdn(); init(); for(int i=1,l,r,u,v;i<=m;i++) { l=rdn(); r=rdn(); u=bh(l); v=bh(r); if(v-u<=1) { ans=0; for(int j=l;j<=r;j++) ct[a[j]]=0; for(int j=l;j<=r;j++) ans+=(ct[a[j]]<<1)+1,ct[a[j]]++; printf("%lld ",ans);continue; } ans=sm[v-1][u+1]; int L=u*base,R=(v-1)*base; for(int j=l;j<=L;j++) { ans+=((cnt[v-1][a[j]]-cnt[u][a[j]])<<1)+1; cnt[v-1][a[j]]++; } for(int j=R+1;j<=r;j++) { ans+=((cnt[v-1][a[j]]-cnt[u][a[j]])<<1)+1; cnt[v-1][a[j]]++; } for(int j=l;j<=L;j++) cnt[v-1][a[j]]--; for(int j=R+1;j<=r;j++) cnt[v-1][a[j]]--; printf("%lld ",ans); } return 0; }
以上是关于bzoj 3781 小B的询问——分块的主要内容,如果未能解决你的问题,请参考以下文章