BZOJ4540: [Hnoi2016]序列
【传送门:BZOJ4540】
简要题意:
给出长度为n的序列,给出m个询问,每个询问输入l,r
每个询问输出l到r的序列中的所有子串中的最小值的和
题解:
莫队+RMQ+乱搞
太烦了,搞了三个小时,不想写题解了
参考代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> using namespace std; typedef long long LL; int a[110000]; int belong[110000]; struct question { int l,r,id;LL d; }q[110000]; bool cmp1(question n1,question n2) { if(belong[n1.l]<belong[n2.l]) return true; if(belong[n1.l]>belong[n2.l]) return false; if(n1.r<n2.r) return true; if(n1.r>n2.r) return false; return false; } bool cmp2(question n1,question n2) { return n1.id<n2.id; } int bin[21]; int mn[21][110000],md[21][110000]; int Log[110000]; int n; void getmn() { bin[0]=1;for(int i=1;i<=20;i++) bin[i]=bin[i-1]<<1; Log[0]=-1; for(int i=1;i<=n;i++) Log[i]=Log[i/2]+1; for(int i=1;i<=n;i++) mn[0][i]=a[i],md[0][i]=i; for(int i=1;i<=Log[n];i++) { for(int j=1;j<=n;j++) { if(j+bin[i]-1<=n) { if(mn[i-1][j]<mn[i-1][j+bin[i-1]]) mn[i][j]=mn[i-1][j],md[i][j]=md[i-1][j]; else mn[i][j]=mn[i-1][j+bin[i-1]],md[i][j]=md[i-1][j+bin[i-1]]; } } } } int sta[110000],tp; LL f1[110000],f2[110000]; LL ans; int findid(int l,int r) { int t=Log[r-l+1]; if(mn[t][l]<mn[t][r-bin[t]+1]) return md[t][l]; else return md[t][r-bin[t]+1]; } int main() { int m; scanf("%d%d",&n,&m); int block=int(sqrt(n)); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); belong[i]=(i-1)/block+1; } getmn(); a[0]=0; int tp=0; sta[++tp]=0; for(int i=1;i<=n;i++) { while(tp>0&&a[sta[tp]]>a[i]) tp--; f1[i]=f1[sta[tp]]+LL(a[i])*LL(i-sta[tp]); sta[++tp]=i; } tp=0;sta[++tp]=n+1; for(int i=n;i>=1;i--) { while(tp>0&&a[sta[tp]]>a[i]) tp--; f2[i]=f2[sta[tp]]+LL(a[i])*LL(sta[tp]-i); sta[++tp]=i; } for(int i=1;i<=m;i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q+1,q+m+1,cmp1); int l=1,r=1; ans=a[1]; for(int i=1;i<=m;i++) { while(r<q[i].r) { r++; int t=findid(l,r); ans+=LL(t-l+1)*a[t]; ans+=f1[r]-f1[t]; } while(r>q[i].r) { int t=findid(l,r); ans-=LL(t-l+1)*a[t]; ans-=f1[r]-f1[t]; r--; } while(l<q[i].l) { int t=findid(l,r); ans-=LL(r-t+1)*a[t]; ans-=f2[l]-f2[t]; l++; } while(l>q[i].l) { l--; int t=findid(l,r); ans+=LL(r-t+1)*a[t]; ans+=f2[l]-f2[t]; } q[i].d=ans; } sort(q+1,q+m+1,cmp2); for(int i=1;i<=m;i++) printf("%lld\n",q[i].d); return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚