HNOI 2016 D2T1 序列 (sequence)

来源:互联网 发布:mac mini 2017 编辑:程序博客网 时间:2024/06/10 01:31

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


0 0