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;
}