http://yuxj173.github.io/2016/04/18/hnoi2016/#more
考场上唯一想出来的题,结果TM莫队写错了。。。
不过题解似乎有更神的莫队做法(优化过的莫队?)
不过块似乎分得有点问题,2S左右出解
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int inf=(1e9)+7; #define rep(i,l,r) for(int i=l;i<=r;i++) #define per(i,r,l) for(int i=r;i>=l;i--) typedef long long ll; const int N=100000+5; int b[N]; struct Query{ int l,r,id; bool operator < (const Query &rhs)const{ if(b[l]==b[rhs.l])return r<rhs.r; return b[l]<b[rhs.l]; } }q[N]; ll a[N]; int st[N][20],n,log_2[N]; bool cmp(int i,int j){ return a[i]<a[j]; } void rmq_init(){ rep(i,1,n)st[i][0]=i; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++) st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1],cmp); } int rmq(int l,int r){ int k=log_2[r-l+1]; return min(st[l][k],st[r-(1<<k)+1][k],cmp); } int pa[N]; int find(int x,ll y){ return a[x]<y?x:pa[x]=find(pa[x],y); } ll res[N],depl[N],depr[N]; int que[N]; ll calcl(int l,int r){ int pos=rmq(l,r); return a[pos]*(r-pos+1)+depr[l]-depr[pos]; } ll calcr(int l,int r){ int pos=rmq(l,r); return a[pos]*(pos-l+1)+depl[r]-depl[pos]; } ll query(int l,int r){ ll ans=0; rep(i,l,r)ans+=calcr(l,i); return ans; } int main(){ freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); int k;scanf("%d%d",&n,&k); rep(i,1,n)scanf("%lld",&a[i]);rmq_init(); a[0]=a[n+1]=-inf; int tp;que[tp=0]=0; rep(i,1,n){ while(a[i]<a[que[tp]])tp--; depl[i]=depl[que[tp]]+a[i]*(i-que[tp]); que[++tp]=i; } que[tp=0]=n+1; per(i,n,1){ while(a[i]<a[que[tp]])tp--; depr[i]=depr[que[tp]]+a[i]*(que[tp]-i); que[++tp]=i; } int m=sqrt(n+0.5); rep(i,1,n)b[i]=(i-1)/m; rep(i,1,k)scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i; sort(q+1,q+1+k); rep(i,2,n)log_2[i]=log_2[i>>1]+1; ll ans;b[0]=-1; int ql,qr,last=0; rep(i,1,k){ if(b[q[i].l]==b[q[i].r]) res[q[i].id]=query(q[i].l,q[i].r); else{ ql=m*(b[q[i].l]+1); if(b[q[i].l]!=b[q[last].l])ans=0,qr=m*(b[q[i].l]+1)-1; while(qr<q[i].r)ans+=calcr(ql,++qr); ll tmp=ans; while(q[i].l<ql)tmp+=calcl(--ql,qr); res[q[i].id]=tmp; last=i; } } rep(i,1,k)printf("%lld\n",res[i]); return 0; }